From 22dd3d3c11f70c6d77100d3e7dfaa48e684bed76 Mon Sep 17 00:00:00 2001
From: Moritzjenny <moritzjenny@hotmail.com>
Date: Thu, 15 Aug 2019 13:54:36 +0200
Subject: [PATCH] OO-4096:Open API documentation REST API

---
 .../calendar/restapi/CalWebService.java       | 78 ++++++++++++++++++-
 .../restapi/UserCalendarWebService.java       | 39 +++++++++-
 .../info/restapi/InfoMessagesWebService.java  |  3 +
 .../restapi/Office365WebService.java          |  3 +
 .../EfficiencyStatementWebService.java        |  3 +
 .../restapi/CertificationWebService.java      |  3 +
 .../course/db/restapi/CourseDbWebService.java |  3 +
 .../olat/course/nodes/co/COWebService.java    |  3 +
 .../olat/course/nodes/en/ENWebService.java    |  3 +
 .../CurriculumElementTypesWebService.java     |  3 +
 .../restapi/CurriculumsWebService.java        |  3 +
 .../restapi/DocumentPoolModuleWebService.java |  3 +
 .../fo/restapi/ForumCourseNodeWebService.java |  3 +
 .../fo/restapi/ForumImportWebService.java     |  5 ++
 .../modules/fo/restapi/ForumWebService.java   | 34 ++++++++
 .../fo/restapi/MyForumsWebService.java        |  4 +
 .../restapi/LectureBlocksRootWebService.java  |  3 +
 .../qpool/restapi/QuestionPoolWebService.java |  3 +
 .../restapi/TaxonomyModuleWebService.java     |  3 +
 .../vitero/restapi/ViteroWebService.java      |  3 +
 .../modules/wiki/restapi/WikisWebService.java |  3 +
 .../olat/restapi/_spring/restApiContext.xml   |  2 +
 .../org/olat/restapi/api/ApiWebService.java   |  3 +
 .../group/LearningGroupWebService.java        |  3 +
 .../restapi/repository/CatalogWebService.java |  3 +
 .../RepositoryEntriesWebService.java          | 25 +++++-
 .../RepositoryEntryLifecycleWebService.java   |  3 +
 .../repository/SharedFolderWebService.java    |  3 +
 .../course/CourseAssessmentWebService.java    |  4 +
 .../course/CourseElementWebService.java       |  3 +
 .../course/CourseGroupWebService.java         |  3 +
 .../CourseResourceFolderWebService.java       |  3 +
 .../repository/course/CoursesWebService.java  |  3 +
 .../java/org/olat/restapi/support/Ping.java   |  3 +
 .../system/OpenOLATStatisticsWebService.java  |  4 +
 .../olat/restapi/system/SystemWebService.java |  3 +
 .../user/restapi/OrganisationsWebService.java |  3 +
 .../user/restapi/RelationRolesWebService.java |  3 +
 .../restapi/UserAuthenticationWebService.java |  3 +
 .../org/olat/user/restapi/UserWebService.java |  4 +
 .../java/org/olat/restapi/DataGenerator.java  |  0
 41 files changed, 282 insertions(+), 7 deletions(-)
 create mode 100644 src/test/java/org/olat/restapi/DataGenerator.java

diff --git a/src/main/java/org/olat/commons/calendar/restapi/CalWebService.java b/src/main/java/org/olat/commons/calendar/restapi/CalWebService.java
index 76dc5ebd9ab..de557eefbd2 100644
--- a/src/main/java/org/olat/commons/calendar/restapi/CalWebService.java
+++ b/src/main/java/org/olat/commons/calendar/restapi/CalWebService.java
@@ -31,7 +31,9 @@ import java.util.Collections;
 import java.util.List;
 import java.util.UUID;
 
+import javax.management.DescriptorKey;
 import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.ApplicationPath;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.DefaultValue;
@@ -54,6 +56,19 @@ import org.olat.commons.calendar.ui.components.KalendarRenderWrapper;
 import org.olat.core.CoreSpringFactory;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.util.StringHelper;
+import org.olat.restapi.support.vo.RepositoryEntryVO;
+import org.springframework.context.annotation.Description;
+
+import io.swagger.v3.oas.annotations.OpenAPIDefinition;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.info.License;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.info.Info;
 
 /**
  * 
@@ -61,6 +76,9 @@ import org.olat.core.util.StringHelper;
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
+
+
+@Tag (name = "Calendar")
 public class CalWebService {
 	
 	private final KalendarRenderWrapper calendar;
@@ -71,9 +89,20 @@ public class CalWebService {
 	
 	@GET
 	@Path("events")
+	@Operation(summary = "List events from a calendar.", description = "Returns list of events from a specific calendar.")
+	@ApiResponses({
+			@ApiResponse(responseCode = "200", description = "Request was successful.",
+				content = {
+					@Content(mediaType = "application/json", schema = @Schema(implementation = EventVO.class)),
+					@Content(mediaType = "application/xml", schema = @Schema(implementation = EventVO.class))
+				} 
+			),
+			@ApiResponse(responseCode = "401", description = "Not authorized."),
+			@ApiResponse(responseCode = "404", description = "Not found.")}
+	)	
 	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
-	public Response getEventsByCalendar(@QueryParam("start") @DefaultValue("0") Integer start,
-			@QueryParam("limit") @DefaultValue("25") Integer limit,
+	public Response getEventsByCalendar(@QueryParam("start")@Parameter(description = "Set the date for the earliest event.") @DefaultValue("0") Integer start,
+			@QueryParam("limit")  @Parameter(description = "Limit the amount of events to be returned.") @DefaultValue("25") Integer limit,
 			@QueryParam("onlyFuture") @DefaultValue("false") Boolean onlyFuture,
 			@Context HttpServletRequest httpRequest, @Context Request request) {
 		
@@ -100,6 +129,7 @@ public class CalWebService {
 	
 	@DELETE
 	@Path("events/{eventId}")
+	@Operation(summary = "Delete specific event.", description = "Deletes a specific event in a calendar.")
 	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
 	@Consumes({MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
 	public Response deleteEventByCalendar(@PathParam("eventId") String eventId,
@@ -133,6 +163,17 @@ public class CalWebService {
 	
 	@PUT
 	@Path("event")
+	@Operation(summary = "Put a specific event.", description = "Puts a specific event in a specific calendar.")
+	@ApiResponses(value = {
+			@ApiResponse(responseCode = "200",
+				content = {
+					@Content(mediaType = "application/json", schema = @Schema(implementation = EventVO.class)),
+					@Content(mediaType = "application/xml", schema = @Schema(implementation = EventVO.class))
+				}
+			),
+			@ApiResponse(responseCode = "401", description = "Not authorized."),
+			@ApiResponse(responseCode = "404", description = "Not found.")}
+		)
 	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
 	@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
 	public Response putEventByCalendar(EventVO event, @Context HttpServletRequest httpRequest) {
@@ -142,6 +183,17 @@ public class CalWebService {
 	
 	@PUT
 	@Path("events")
+	@Operation(summary = "Put specific events.", description = "Puts specific events in a specific calendar.")
+	@ApiResponses(value = {
+			@ApiResponse(responseCode = "200",
+				content = {
+					@Content(mediaType = "application/json", schema = @Schema(implementation = EventVO[].class)),
+					@Content(mediaType = "application/xml", schema = @Schema(implementation = EventVO[].class))
+				}
+			),
+			@ApiResponse(responseCode = "401", description = "Not authorized."),
+			@ApiResponse(responseCode = "404", description = "Not found.")}
+		)
 	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
 	@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
 	public Response putEventsByCalendar(EventVO[] eventArray, @Context HttpServletRequest httpRequest) {
@@ -154,6 +206,17 @@ public class CalWebService {
 	
 	@POST
 	@Path("event")
+	@Operation(summary = "Post a specific event.", description = "Posts a specific event in a specific calendar.")
+	@ApiResponses(value = {
+			@ApiResponse(responseCode = "200",
+				content = {
+					@Content(mediaType = "application/json", schema = @Schema(implementation = EventVO.class)),
+					@Content(mediaType = "application/xml", schema = @Schema(implementation = EventVO.class))
+				}
+			),
+			@ApiResponse(responseCode = "401", description = "Not authorized."),
+			@ApiResponse(responseCode = "404", description = "Not found.")}
+		)
 	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
 	@Consumes({MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
 	public Response postEventByCalendar(EventVO event, @Context HttpServletRequest httpRequest) {
@@ -163,6 +226,17 @@ public class CalWebService {
 	
 	@POST
 	@Path("events")
+	@Operation(summary = "Post specific events.", description = "Posts specific events in a specific calendar.")
+	@ApiResponses(value = {
+			@ApiResponse(responseCode = "200",
+				content = {
+					@Content(mediaType = "application/json", schema = @Schema(implementation = EventVO[].class)),
+					@Content(mediaType = "application/xml", schema = @Schema(implementation = EventVO[].class))
+				}
+			),
+			@ApiResponse(responseCode = "401", description = "Not authorized."),
+			@ApiResponse(responseCode = "404", description = "Not found.")}
+		)
 	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
 	@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
 	public Response postEventsByCalendar(EventVO[] eventArray, @Context HttpServletRequest httpRequest) {
diff --git a/src/main/java/org/olat/commons/calendar/restapi/UserCalendarWebService.java b/src/main/java/org/olat/commons/calendar/restapi/UserCalendarWebService.java
index 46ea4e60d73..b1e2b9220bb 100644
--- a/src/main/java/org/olat/commons/calendar/restapi/UserCalendarWebService.java
+++ b/src/main/java/org/olat/commons/calendar/restapi/UserCalendarWebService.java
@@ -42,6 +42,7 @@ import javax.ws.rs.core.Request;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 
+import org.apache.logging.log4j.Logger;
 import org.olat.basesecurity.BaseSecurity;
 import org.olat.basesecurity.OrganisationRoles;
 import org.olat.collaboration.CollaborationManager;
@@ -56,7 +57,6 @@ import org.olat.core.gui.UserRequest;
 import org.olat.core.id.Identity;
 import org.olat.core.id.IdentityEnvironment;
 import org.olat.core.id.Roles;
-import org.apache.logging.log4j.Logger;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.nodes.INode;
 import org.olat.core.util.tree.Visitor;
@@ -81,12 +81,21 @@ import org.olat.restapi.security.RestSecurityHelper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  */
+@Tag(name = "Users")
 @Component
-@Path("users/{identityKey}/calendars")
+@Path("/users/{identityKey}/calendars")
 public class UserCalendarWebService {
 	
 	private static final Logger log = Tracing.createLoggerFor(UserCalendarWebService.class);
@@ -106,6 +115,17 @@ public class UserCalendarWebService {
 	
 	
 	@GET
+	@Tag(name = "Calendar")
+	@Operation(summary = "List calendars of a specific user.", description = "Returns list of calendars of a specific user. Will always return the administrator's calendars for administrators.")
+	@ApiResponses({
+		@ApiResponse(responseCode = "200", description = "Request was successful.",
+			content = {
+				@Content(mediaType = "application/json", schema = @Schema(implementation = CalendarVO.class)),
+				@Content(mediaType = "application/xml", schema = @Schema(implementation = CalendarVO.class))
+			}, links = {}),
+		@ApiResponse(responseCode = "401", description = "Not authorized."),
+		@ApiResponse(responseCode = "404", description = "Not found.")}
+		)
 	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
 	public Response getCalendars(@PathParam("identityKey") Long identityKey, @Context HttpServletRequest httpRequest) {
 		UserRequest ureq = getUserRequest(httpRequest);
@@ -153,10 +173,21 @@ public class UserCalendarWebService {
 
 	@GET
 	@Path("events")
+	@Operation(summary = "List all events.", description = "Returns list of all events in for a specific user.")
+	@ApiResponses({
+		@ApiResponse(responseCode = "200", description = "Request was successful.",
+			content = {
+				@Content(mediaType = "application/json", schema = @Schema(implementation = EventVO[].class)),
+				@Content(mediaType = "application/xml", schema = @Schema(implementation = EventVO[].class))
+			} 
+		),
+		@ApiResponse(responseCode = "401", description = "Not authorized."),
+		@ApiResponse(responseCode = "404", description = "Not found.")}
+)	
 	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
 	public Response getEvents(@PathParam("identityKey") Long identityKey,
-			@QueryParam("start") @DefaultValue("0") Integer start,
-			@QueryParam("limit") @DefaultValue("25") Integer limit,
+			@QueryParam("start")  @Parameter(description = "Set the date for the earliest event.")@DefaultValue("0") Integer start,
+			@QueryParam("limit")  @Parameter(description = "Limit the amount of events to be returned.") @DefaultValue("25") Integer limit,
 			@QueryParam("onlyFuture") @DefaultValue("false") Boolean onlyFuture,
 			@Context HttpServletRequest httpRequest, @Context Request request) {
 		
diff --git a/src/main/java/org/olat/commons/info/restapi/InfoMessagesWebService.java b/src/main/java/org/olat/commons/info/restapi/InfoMessagesWebService.java
index 1a1f47f4c97..6d2cd4639a1 100644
--- a/src/main/java/org/olat/commons/info/restapi/InfoMessagesWebService.java
+++ b/src/main/java/org/olat/commons/info/restapi/InfoMessagesWebService.java
@@ -48,6 +48,8 @@ import org.olat.core.util.resource.OresHelper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * Description:<br>
@@ -56,6 +58,7 @@ import org.springframework.stereotype.Component;
  * Initial Date:  29 jul. 2010 <br>
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  */
+@Tag(name = "Infomessages")
 @Component
 @Path("infomessages")
 public class InfoMessagesWebService {
diff --git a/src/main/java/org/olat/core/commons/services/doceditor/office365/restapi/Office365WebService.java b/src/main/java/org/olat/core/commons/services/doceditor/office365/restapi/Office365WebService.java
index ff2ec473412..7120b931dd7 100644
--- a/src/main/java/org/olat/core/commons/services/doceditor/office365/restapi/Office365WebService.java
+++ b/src/main/java/org/olat/core/commons/services/doceditor/office365/restapi/Office365WebService.java
@@ -55,6 +55,8 @@ import org.springframework.stereotype.Service;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * The simplest way to test this class is to use the interactice WOPI Validation application.
  * https://wopi.readthedocs.io/en/latest/build_test_ship/validator.html#interactive-wopi-validation
@@ -63,6 +65,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
  * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
  *
  */
+@Tag(name = "Office365")
 @Service
 @Path("/office365/wopi/files/{fileId}")
 public class Office365WebService {
diff --git a/src/main/java/org/olat/course/assessment/restapi/EfficiencyStatementWebService.java b/src/main/java/org/olat/course/assessment/restapi/EfficiencyStatementWebService.java
index 5bf1f7f3aed..52404a8997b 100644
--- a/src/main/java/org/olat/course/assessment/restapi/EfficiencyStatementWebService.java
+++ b/src/main/java/org/olat/course/assessment/restapi/EfficiencyStatementWebService.java
@@ -48,12 +48,15 @@ import org.olat.resource.OLATResourceManager;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * Initial date: 17.11.2014<br>
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
+@Tag(name = "Repo")
 @Component
 @Path("repo/courses/{resourceKey}/statements")
 public class EfficiencyStatementWebService {
diff --git a/src/main/java/org/olat/course/certificate/restapi/CertificationWebService.java b/src/main/java/org/olat/course/certificate/restapi/CertificationWebService.java
index 79cb582b9d6..985cc063ec8 100644
--- a/src/main/java/org/olat/course/certificate/restapi/CertificationWebService.java
+++ b/src/main/java/org/olat/course/certificate/restapi/CertificationWebService.java
@@ -64,12 +64,15 @@ import org.olat.restapi.support.ObjectFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * Initial date: 17.11.2014<br>
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
+@Tag(name = "Repo")
 @Component
 @Path("repo/courses/{resourceKey}/certificates")
 public class CertificationWebService {
diff --git a/src/main/java/org/olat/course/db/restapi/CourseDbWebService.java b/src/main/java/org/olat/course/db/restapi/CourseDbWebService.java
index 6087a1f2844..3ad4ae0287f 100644
--- a/src/main/java/org/olat/course/db/restapi/CourseDbWebService.java
+++ b/src/main/java/org/olat/course/db/restapi/CourseDbWebService.java
@@ -54,6 +54,8 @@ import org.olat.restapi.support.vo.KeyValuePair;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * Description:<br>
  * Access the custom dbs of a course
@@ -62,6 +64,7 @@ import org.springframework.stereotype.Component;
  * Initial Date:	 *7 apr. 2010 <br>
  * @author srosse, stephane.rosse@frentix.com
  */
+@Tag(name = "Repo")
 @Component
 @Path("repo/courses/{courseId}/db/{category}")
 public class CourseDbWebService {
diff --git a/src/main/java/org/olat/course/nodes/co/COWebService.java b/src/main/java/org/olat/course/nodes/co/COWebService.java
index 97a616beba4..75a3099195b 100755
--- a/src/main/java/org/olat/course/nodes/co/COWebService.java
+++ b/src/main/java/org/olat/course/nodes/co/COWebService.java
@@ -65,6 +65,8 @@ import org.olat.modules.ModuleConfiguration;
 import org.olat.restapi.repository.course.AbstractCourseNodeWebService;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * Description:<br>
@@ -75,6 +77,7 @@ import org.springframework.stereotype.Component;
  * @author srosse, stephane.rosse@frentix.com
  * @author Dirk Furrer
  */
+@Tag(name = "Repo")
 @Component
 @Path("repo/courses/{courseId}/elements/contact")
 public class COWebService extends AbstractCourseNodeWebService {
diff --git a/src/main/java/org/olat/course/nodes/en/ENWebService.java b/src/main/java/org/olat/course/nodes/en/ENWebService.java
index cba0972364a..94dba4481a0 100644
--- a/src/main/java/org/olat/course/nodes/en/ENWebService.java
+++ b/src/main/java/org/olat/course/nodes/en/ENWebService.java
@@ -54,6 +54,8 @@ import org.olat.restapi.support.vo.GroupVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * Description:<br>
@@ -63,6 +65,7 @@ import org.springframework.stereotype.Component;
  * Initial Date:  10 mai 2010 <br>
  * @author srosse, stephane.rosse@frentix.com
  */
+@Tag(name = "Repo")
 @Component
 @Path("repo/courses/{courseId}/elements/enrollment")
 public class ENWebService extends AbstractCourseNodeWebService {
diff --git a/src/main/java/org/olat/modules/curriculum/restapi/CurriculumElementTypesWebService.java b/src/main/java/org/olat/modules/curriculum/restapi/CurriculumElementTypesWebService.java
index 75d9f689d6b..503ea870236 100644
--- a/src/main/java/org/olat/modules/curriculum/restapi/CurriculumElementTypesWebService.java
+++ b/src/main/java/org/olat/modules/curriculum/restapi/CurriculumElementTypesWebService.java
@@ -45,6 +45,8 @@ import org.olat.modules.curriculum.model.CurriculumElementTypeRefImpl;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * The security check is done by the curriculums web service.
  * 
@@ -52,6 +54,7 @@ import org.springframework.stereotype.Component;
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
+@Tag(name = "Curriculum")
 @Component
 @Path("curriculum/types")
 public class CurriculumElementTypesWebService {
diff --git a/src/main/java/org/olat/modules/curriculum/restapi/CurriculumsWebService.java b/src/main/java/org/olat/modules/curriculum/restapi/CurriculumsWebService.java
index 0ab4beac467..af609ab55d4 100644
--- a/src/main/java/org/olat/modules/curriculum/restapi/CurriculumsWebService.java
+++ b/src/main/java/org/olat/modules/curriculum/restapi/CurriculumsWebService.java
@@ -62,12 +62,15 @@ import org.olat.user.restapi.UserVOFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * Initial date: 15 mai 2018<br>
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
+@Tag(name = "Curriculum")
 @Component
 @Path("curriculum")
 public class CurriculumsWebService {
diff --git a/src/main/java/org/olat/modules/docpool/restapi/DocumentPoolModuleWebService.java b/src/main/java/org/olat/modules/docpool/restapi/DocumentPoolModuleWebService.java
index eb85456fd84..8c7a8d3b757 100644
--- a/src/main/java/org/olat/modules/docpool/restapi/DocumentPoolModuleWebService.java
+++ b/src/main/java/org/olat/modules/docpool/restapi/DocumentPoolModuleWebService.java
@@ -41,12 +41,15 @@ import org.olat.modules.taxonomy.model.TaxonomyRefImpl;
 import org.olat.modules.taxonomy.restapi.TaxonomyWebService;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * Initial date: 5 Oct 2017<br>
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
+@Tag(name = "Docpool")
 @Component
 @Path("docpool")
 public class DocumentPoolModuleWebService {
diff --git a/src/main/java/org/olat/modules/fo/restapi/ForumCourseNodeWebService.java b/src/main/java/org/olat/modules/fo/restapi/ForumCourseNodeWebService.java
index 4a5d5c3999b..bf00414e0ce 100644
--- a/src/main/java/org/olat/modules/fo/restapi/ForumCourseNodeWebService.java
+++ b/src/main/java/org/olat/modules/fo/restapi/ForumCourseNodeWebService.java
@@ -76,6 +76,8 @@ import org.olat.restapi.security.RestSecurityHelper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * Description:<br>
@@ -85,6 +87,7 @@ import org.springframework.stereotype.Component;
  * Initial Date:  20.12.2010 <br>
  * @author skoeber
  */
+@Tag(name = "Repo")
 @Component
 @Path("repo/courses/{courseId}/elements/forum")
 public class ForumCourseNodeWebService extends AbstractCourseNodeWebService {
diff --git a/src/main/java/org/olat/modules/fo/restapi/ForumImportWebService.java b/src/main/java/org/olat/modules/fo/restapi/ForumImportWebService.java
index 402cf3e5029..5cee8bd66aa 100644
--- a/src/main/java/org/olat/modules/fo/restapi/ForumImportWebService.java
+++ b/src/main/java/org/olat/modules/fo/restapi/ForumImportWebService.java
@@ -33,6 +33,9 @@ import org.olat.modules.fo.manager.ForumManager;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * Description:<br>
@@ -42,7 +45,9 @@ import org.springframework.stereotype.Component;
  * Initial Date:  26 aug. 2010 <br>
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  */
+@Tag(name = "Repo")
 @Component
+
 @Path("repo/forums")
 public class ForumImportWebService {
 	
diff --git a/src/main/java/org/olat/modules/fo/restapi/ForumWebService.java b/src/main/java/org/olat/modules/fo/restapi/ForumWebService.java
index 3b9e58be8ac..529992c9448 100644
--- a/src/main/java/org/olat/modules/fo/restapi/ForumWebService.java
+++ b/src/main/java/org/olat/modules/fo/restapi/ForumWebService.java
@@ -60,6 +60,7 @@ import org.apache.commons.io.IOUtils;
 import org.olat.basesecurity.BaseSecurity;
 import org.olat.basesecurity.OrganisationRoles;
 import org.olat.basesecurity.model.IdentityRefImpl;
+import org.olat.commons.calendar.restapi.CalendarVO;
 import org.olat.core.commons.services.vfs.restapi.VFSStreamingOutput;
 import org.olat.core.gui.media.ServletUtil;
 import org.olat.core.id.Identity;
@@ -85,6 +86,13 @@ import org.olat.restapi.support.vo.File64VO;
 import org.olat.restapi.support.vo.FileVO;
 import org.springframework.beans.factory.annotation.Autowired;
 
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * Description:<br>
@@ -94,6 +102,8 @@ import org.springframework.beans.factory.annotation.Autowired;
  * Initial Date:  20 apr. 2010 <br>
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  */
+
+@Tag (name =  "Repo")
 public class ForumWebService {
 	
 	private static final Logger log = Tracing.createLoggerFor(ForumWebService.class);
@@ -154,6 +164,8 @@ public class ForumWebService {
 	 */
 	@GET
 	@Path("threads")
+	@Operation(summary = "Get threads",
+	description = "Retrieves the threads in the forum.")
 	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
 	public Response getThreads(@QueryParam("start") @DefaultValue("0") Integer start,
 			@QueryParam("limit") @DefaultValue("25") Integer limit,  @QueryParam("orderBy") @DefaultValue("creationDate") String orderBy,
@@ -197,6 +209,8 @@ public class ForumWebService {
 	 */
 	@POST
 	@Path("threads")
+	@Operation(summary = "Post threads",
+	description = "Creates a new thread in the forum of the course node.")
 	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
 	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
 	public Response newThreadToForumPost(@FormParam("title") String title,
@@ -221,6 +235,8 @@ public class ForumWebService {
 	 */
 	@PUT
 	@Path("threads")
+	@Operation(summary = "Put threads",
+	description = "Creates a new thread in the forum of the course node.")
 	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
 	public Response newThreadToForum(@QueryParam("title") String title,
 			@QueryParam("body") String body, @QueryParam("authorKey") Long authorKey,
@@ -258,6 +274,8 @@ public class ForumWebService {
 	 */
 	@GET
 	@Path("posts/{threadKey}")
+	@Operation(summary = "Get posts",
+	description = "Retrieves the messages in the thread.")
 	public Response getMessages( @PathParam("threadKey") Long threadKey, @QueryParam("start") @DefaultValue("0") Integer start,
 			@QueryParam("limit") @DefaultValue("25") Integer limit, @QueryParam("orderBy") @DefaultValue("creationDate") String orderBy,
 			@QueryParam("asc") @DefaultValue("true") Boolean asc, @Context HttpServletRequest httpRequest, @Context UriInfo uriInfo,
@@ -302,6 +320,8 @@ public class ForumWebService {
 	 */
 	@POST
 	@Path("posts/{messageKey}")
+	@Operation(summary = "Post posts",
+	description = "Creates a new reply in the forum of the course node.")
 	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
 	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
 	public Response replyToPostPost(@PathParam("messageKey") Long messageKey, @FormParam("title") String title,
@@ -328,6 +348,8 @@ public class ForumWebService {
 	 */
 	@PUT
 	@Path("posts/{messageKey}")
+	@Operation(summary = "Put posts",
+	description = "Creates a new reply in the forum of the course node.")
 	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
 	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
 	public Response replyToPost(@PathParam("messageKey") Long messageKey, @QueryParam("title") String title,
@@ -352,6 +374,8 @@ public class ForumWebService {
 	 */
 	@PUT
 	@Path("posts/{messageKey}")
+	@Operation(summary = "Put posts",
+	description = "Creates a new reply in the forum of the course node.")
 	@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
 	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
 	public Response replyToPost(@PathParam("messageKey") Long messageKey, ReplyVO reply,
@@ -416,6 +440,8 @@ public class ForumWebService {
 	 */
 	@GET
 	@Path("posts/{messageKey}/attachments")
+	@Operation(summary = "Get attachments",
+	description = "Retrieves the attachments of the message.")
 	@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
 	public Response getAttachments(@PathParam("messageKey") Long messageKey, @Context UriInfo uriInfo) {
 		//load message
@@ -442,6 +468,8 @@ public class ForumWebService {
 	 * @return The attachment
 	 */
 	@GET
+	@Operation(summary = "Get attachment",
+	description = "Retrieves the attachment of the message.")
 	@Path("posts/{messageKey}/attachments/{filename}")
 	@Produces({"*/*", MediaType.APPLICATION_OCTET_STREAM})
 	public Response getAttachment(@PathParam("messageKey") Long messageKey, @PathParam("filename") String filename, 
@@ -495,6 +523,8 @@ public class ForumWebService {
 	 * @return Ok
 	 */
 	@POST
+	@Operation(summary = "Post attachment",
+	description = "Upload the attachment of a message, as parameter.")
 	@Path("posts/{messageKey}/attachments")
 	@Consumes(MediaType.MULTIPART_FORM_DATA)
 	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
@@ -528,6 +558,8 @@ public class ForumWebService {
 	 * @return Ok
 	 */
 	@POST
+	@Operation(summary = "Post attachment",
+	description = "Upload the attachment of a message.")
 	@Path("posts/{messageKey}/attachments")
 	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
 	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
@@ -539,6 +571,8 @@ public class ForumWebService {
 	}
 	
 	@PUT
+	@Operation(summary = "Put attachment",
+	description = "Upload the attachment of a message.")
 	@Path("posts/{messageKey}/attachments")
 	@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
 	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
diff --git a/src/main/java/org/olat/modules/fo/restapi/MyForumsWebService.java b/src/main/java/org/olat/modules/fo/restapi/MyForumsWebService.java
index 54cd4d1ba9c..d25e60c858f 100644
--- a/src/main/java/org/olat/modules/fo/restapi/MyForumsWebService.java
+++ b/src/main/java/org/olat/modules/fo/restapi/MyForumsWebService.java
@@ -69,6 +69,8 @@ import org.olat.restapi.group.LearningGroupWebService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * Description:<br>
@@ -78,6 +80,7 @@ import org.springframework.stereotype.Component;
  *
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  */
+@Tag(name = "Users")
 @Component
 @Path("users/{identityKey}/forums")
 public class MyForumsWebService {
@@ -103,6 +106,7 @@ public class MyForumsWebService {
 	 * @param request The REST request
 	 * @return The files
 	 */
+
 	@Path("group/{groupKey}")
 	public ForumWebService getGroupForum(@PathParam("groupKey") Long groupKey, @Context HttpServletRequest request) {
 		if(groupKey == null) {
diff --git a/src/main/java/org/olat/modules/lecture/restapi/LectureBlocksRootWebService.java b/src/main/java/org/olat/modules/lecture/restapi/LectureBlocksRootWebService.java
index a5381d53a7c..aff04053b93 100644
--- a/src/main/java/org/olat/modules/lecture/restapi/LectureBlocksRootWebService.java
+++ b/src/main/java/org/olat/modules/lecture/restapi/LectureBlocksRootWebService.java
@@ -47,12 +47,15 @@ import org.olat.modules.lecture.model.LecturesBlockSearchParameters;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * Initial date: 8 juin 2017<br>
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
+@Tag(name = "Repo")
 @Component
 @Path("repo/lectures")
 public class LectureBlocksRootWebService {
diff --git a/src/main/java/org/olat/modules/qpool/restapi/QuestionPoolWebService.java b/src/main/java/org/olat/modules/qpool/restapi/QuestionPoolWebService.java
index fd883474b01..b2e36d0529e 100644
--- a/src/main/java/org/olat/modules/qpool/restapi/QuestionPoolWebService.java
+++ b/src/main/java/org/olat/modules/qpool/restapi/QuestionPoolWebService.java
@@ -58,12 +58,15 @@ import org.olat.user.restapi.UserVO;
 import org.olat.user.restapi.UserVOFactory;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * Initial date: 8 sept. 2017<br>
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
+@Tag(name = "Qpool")
 @Component
 @Path("qpool/items")
 public class QuestionPoolWebService {
diff --git a/src/main/java/org/olat/modules/taxonomy/restapi/TaxonomyModuleWebService.java b/src/main/java/org/olat/modules/taxonomy/restapi/TaxonomyModuleWebService.java
index a93d458f6b6..9d21c2bfafe 100644
--- a/src/main/java/org/olat/modules/taxonomy/restapi/TaxonomyModuleWebService.java
+++ b/src/main/java/org/olat/modules/taxonomy/restapi/TaxonomyModuleWebService.java
@@ -36,12 +36,15 @@ import org.olat.modules.taxonomy.TaxonomyService;
 import org.olat.modules.taxonomy.model.TaxonomyRefImpl;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * Initial date: 5 Oct 2017<br>
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
+@Tag(name = "Taxonomy")
 @Path("taxonomy")
 @Component
 public class TaxonomyModuleWebService {
diff --git a/src/main/java/org/olat/modules/vitero/restapi/ViteroWebService.java b/src/main/java/org/olat/modules/vitero/restapi/ViteroWebService.java
index c3e58c97822..688e3c72df4 100644
--- a/src/main/java/org/olat/modules/vitero/restapi/ViteroWebService.java
+++ b/src/main/java/org/olat/modules/vitero/restapi/ViteroWebService.java
@@ -28,12 +28,15 @@ import org.olat.core.id.OLATResourceable;
 import org.olat.core.util.resource.OresHelper;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * Initial date: 06.07.2015<br>
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
+@Tag(name = "Vitero")
 @Path("vitero")
 @Component
 public class ViteroWebService {
diff --git a/src/main/java/org/olat/modules/wiki/restapi/WikisWebService.java b/src/main/java/org/olat/modules/wiki/restapi/WikisWebService.java
index c953b4645d9..2dfeb157d5b 100644
--- a/src/main/java/org/olat/modules/wiki/restapi/WikisWebService.java
+++ b/src/main/java/org/olat/modules/wiki/restapi/WikisWebService.java
@@ -44,6 +44,8 @@ import org.olat.repository.model.SearchRepositoryEntryParameters;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * The Wikis Webservice.<br />
@@ -52,6 +54,7 @@ import org.springframework.stereotype.Component;
  * @author strentini, sergio.trentini@frentix.com, http://www.frentix.com
  * 
  */
+@Tag(name = "Repo")
 @Path("repo/wikis")
 @Component
 public class WikisWebService {
diff --git a/src/main/java/org/olat/restapi/_spring/restApiContext.xml b/src/main/java/org/olat/restapi/_spring/restApiContext.xml
index 0d6d34220ad..89f83d36cdb 100644
--- a/src/main/java/org/olat/restapi/_spring/restApiContext.xml
+++ b/src/main/java/org/olat/restapi/_spring/restApiContext.xml
@@ -11,6 +11,8 @@
 	<!-- CXF OpenApiFeature -->  
 	<bean id="openApiFeature" class="org.apache.cxf.jaxrs.openapi.OpenApiFeature">
 		<!-- customize some of the properties -->
+		<property name="useContextBasedConfig" value="true"/>
+		<property name="scan" value="false"/>
 	</bean>
 
 	<jaxrs:server address="/" basePackages="org.olat">
diff --git a/src/main/java/org/olat/restapi/api/ApiWebService.java b/src/main/java/org/olat/restapi/api/ApiWebService.java
index 49bd75a22a5..985b84e17fc 100644
--- a/src/main/java/org/olat/restapi/api/ApiWebService.java
+++ b/src/main/java/org/olat/restapi/api/ApiWebService.java
@@ -31,6 +31,8 @@ import javax.ws.rs.core.Response.Status;
 
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * Description:<br>
@@ -40,6 +42,7 @@ import org.springframework.stereotype.Component;
  * Initial Date:  14 apr. 2010 <br>
  * @author srosse, stephane.rosse@frentix.com
  */
+@Tag(name = "API")
 @Path("api")
 @Component
 public class ApiWebService {
diff --git a/src/main/java/org/olat/restapi/group/LearningGroupWebService.java b/src/main/java/org/olat/restapi/group/LearningGroupWebService.java
index f719b2927aa..2c54ab08fe8 100644
--- a/src/main/java/org/olat/restapi/group/LearningGroupWebService.java
+++ b/src/main/java/org/olat/restapi/group/LearningGroupWebService.java
@@ -85,6 +85,8 @@ import org.olat.user.restapi.UserVO;
 import org.olat.user.restapi.UserVOFactory;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 
 /**
  * Description:<br>
@@ -94,6 +96,7 @@ import org.springframework.stereotype.Component;
  * Initial Date:  23 mar. 2010 <br>
  * @author srosse, stephane.rosse@frentix.com
  */
+@Tag(name = "Groups")
 @Component
 @Path("groups")
 public class LearningGroupWebService {
diff --git a/src/main/java/org/olat/restapi/repository/CatalogWebService.java b/src/main/java/org/olat/restapi/repository/CatalogWebService.java
index 1290c6efc21..38ed5c9f707 100644
--- a/src/main/java/org/olat/restapi/repository/CatalogWebService.java
+++ b/src/main/java/org/olat/restapi/repository/CatalogWebService.java
@@ -77,6 +77,8 @@ import org.olat.user.restapi.UserVOFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * Description:<br>
  * A web service for the catalog
@@ -85,6 +87,7 @@ import org.springframework.stereotype.Component;
  * Initial Date:  5 may 2010 <br>
  * @author srosse, stephane.rosse@frentix.com
  */
+@Tag(name = "Catalog")
 @Component
 @Path("catalog")
 public class CatalogWebService {
diff --git a/src/main/java/org/olat/restapi/repository/RepositoryEntriesWebService.java b/src/main/java/org/olat/restapi/repository/RepositoryEntriesWebService.java
index 645eb712f0e..f9f838c973f 100644
--- a/src/main/java/org/olat/restapi/repository/RepositoryEntriesWebService.java
+++ b/src/main/java/org/olat/restapi/repository/RepositoryEntriesWebService.java
@@ -79,10 +79,17 @@ import org.olat.restapi.support.vo.RepositoryEntryVOes;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.OpenAPIDefinition;
 import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.info.Contact;
+import io.swagger.v3.oas.annotations.info.Info;
+import io.swagger.v3.oas.annotations.info.License;
 import io.swagger.v3.oas.annotations.media.Content;
 import io.swagger.v3.oas.annotations.media.Schema;
-import io.swagger.v3.oas.annotations.responses.*;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+import io.swagger.v3.oas.annotations.servers.Server;
+import io.swagger.v3.oas.annotations.tags.Tag;
 
 /**
  * Description:<br>
@@ -93,7 +100,23 @@ import io.swagger.v3.oas.annotations.responses.*;
  * 
  * @author patrickb, srosse, stephane.rosse@frentix.com
  */
+@Tag(name = "Repo")
 @Component
+@OpenAPIDefinition(
+	info = @Info(
+			title = "OpenOlat REST API",
+			description = "This is the documentation of the OpenOlat REST API.",
+			contact = @Contact(
+					name=  "OpenOlat",
+					url = "https://www.openolat.org"
+				),
+			license = @License(
+					name = "Apache 2.0",
+					url = "https://github.com/OpenOLAT/OpenOLAT/blob/master/LICENSE"
+				)
+		),
+	servers = { @Server(url = "/restapi") }
+)
 @Path("repo/entries")
 public class RepositoryEntriesWebService {
 	
diff --git a/src/main/java/org/olat/restapi/repository/RepositoryEntryLifecycleWebService.java b/src/main/java/org/olat/restapi/repository/RepositoryEntryLifecycleWebService.java
index 7e50edeed4b..9b494995adc 100644
--- a/src/main/java/org/olat/restapi/repository/RepositoryEntryLifecycleWebService.java
+++ b/src/main/java/org/olat/restapi/repository/RepositoryEntryLifecycleWebService.java
@@ -40,12 +40,15 @@ import org.olat.restapi.support.vo.RepositoryEntryLifecycleVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * Initial date: 10.06.2013<br>
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
+@Tag(name = "Repo")
 @Component
 @Path("repo/lifecycle")
 public class RepositoryEntryLifecycleWebService {
diff --git a/src/main/java/org/olat/restapi/repository/SharedFolderWebService.java b/src/main/java/org/olat/restapi/repository/SharedFolderWebService.java
index 715010598c0..1c20e2a3bce 100644
--- a/src/main/java/org/olat/restapi/repository/SharedFolderWebService.java
+++ b/src/main/java/org/olat/restapi/repository/SharedFolderWebService.java
@@ -56,6 +56,8 @@ import org.olat.restapi.support.vo.LinkVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * Description:<br>
  * A web service for the catalog
@@ -64,6 +66,7 @@ import org.springframework.stereotype.Component;
  * Initial Date:  5 may 2017 <br>
  * @author Stephan Clemenz, VCRP
  */
+@Tag(name = "Repo")
 @Component
 @Path("repo/sharedfolder")
 public class SharedFolderWebService {
diff --git a/src/main/java/org/olat/restapi/repository/course/CourseAssessmentWebService.java b/src/main/java/org/olat/restapi/repository/course/CourseAssessmentWebService.java
index 7bffd3adf46..eca87b92539 100644
--- a/src/main/java/org/olat/restapi/repository/course/CourseAssessmentWebService.java
+++ b/src/main/java/org/olat/restapi/repository/course/CourseAssessmentWebService.java
@@ -87,6 +87,8 @@ import org.olat.restapi.support.vo.AssessableResultsVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * Description:<br>
@@ -96,6 +98,7 @@ import org.springframework.stereotype.Component;
  * Initial Date:  7 apr. 2010 <br>
  * @author srosse, stephane.rosse@frentix.com
  */
+@Tag(name = "Repo")
 @Component
 @Path("repo/courses/{courseId}/assessments")
 public class CourseAssessmentWebService {
@@ -191,6 +194,7 @@ public class CourseAssessmentWebService {
 	 * @param request The REST request
 	 * @return
 	 */
+	
 	@GET
 	@Path("users/{identityKey}")
 	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
diff --git a/src/main/java/org/olat/restapi/repository/course/CourseElementWebService.java b/src/main/java/org/olat/restapi/repository/course/CourseElementWebService.java
index 91463d31951..84939b38ddd 100644
--- a/src/main/java/org/olat/restapi/repository/course/CourseElementWebService.java
+++ b/src/main/java/org/olat/restapi/repository/course/CourseElementWebService.java
@@ -81,6 +81,8 @@ import org.olat.restapi.support.vo.elements.TaskConfigVO;
 import org.olat.restapi.support.vo.elements.TestConfigVO;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 
 /**
  * This interface provides course building capabilities from our REST API.
@@ -89,6 +91,7 @@ import org.springframework.stereotype.Component;
  * 
  * @author cbuckley, srosse, stephane.rosse@frentix.com
  */
+@Tag(name = "Repo")
 @Component
 @Path("repo/courses/{courseId}/elements")
 public class CourseElementWebService extends AbstractCourseNodeWebService {
diff --git a/src/main/java/org/olat/restapi/repository/course/CourseGroupWebService.java b/src/main/java/org/olat/restapi/repository/course/CourseGroupWebService.java
index 1fc933d17f4..58623e92db6 100644
--- a/src/main/java/org/olat/restapi/repository/course/CourseGroupWebService.java
+++ b/src/main/java/org/olat/restapi/repository/course/CourseGroupWebService.java
@@ -65,6 +65,8 @@ import org.olat.restapi.security.RestSecurityHelper;
 import org.olat.restapi.support.ObjectFactory;
 import org.olat.restapi.support.vo.GroupVO;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * Description:<br>
@@ -74,6 +76,7 @@ import org.olat.restapi.support.vo.GroupVO;
  * Initial Date:  7 apr. 2010 <br>
  * @author srosse, stephane.rosse@frentix.com
  */
+@Tag(name = "Groups")
 public class CourseGroupWebService {
 	
 	private static final String VERSION = "1.0";
diff --git a/src/main/java/org/olat/restapi/repository/course/CourseResourceFolderWebService.java b/src/main/java/org/olat/restapi/repository/course/CourseResourceFolderWebService.java
index 8cca17de039..8ec2d8cb449 100644
--- a/src/main/java/org/olat/restapi/repository/course/CourseResourceFolderWebService.java
+++ b/src/main/java/org/olat/restapi/repository/course/CourseResourceFolderWebService.java
@@ -79,6 +79,8 @@ import org.olat.restapi.support.vo.LinkVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * Description:<br>
@@ -90,6 +92,7 @@ import org.springframework.stereotype.Component;
  * Initial Date:  26 apr. 2010 <br>
  * @author srosse, stephane.rosse@frentix.com
  */
+@Tag(name = "Repo")
 @Component
 @Path("repo/courses/{courseId}/resourcefolders")
 public class CourseResourceFolderWebService {
diff --git a/src/main/java/org/olat/restapi/repository/course/CoursesWebService.java b/src/main/java/org/olat/restapi/repository/course/CoursesWebService.java
index 8a840056a1d..e1f4ac3ccf8 100644
--- a/src/main/java/org/olat/restapi/repository/course/CoursesWebService.java
+++ b/src/main/java/org/olat/restapi/repository/course/CoursesWebService.java
@@ -91,6 +91,8 @@ import org.olat.restapi.support.vo.CourseVOes;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  *
  * Description:<br>
@@ -100,6 +102,7 @@ import org.springframework.stereotype.Component;
  * Initial Date:  27 apr. 2010 <br>
  * @author srosse, stephane.rosse@frentix.com
  */
+@Tag(name = "Repo")
 @Component
 @Path("repo/courses")
 public class CoursesWebService {
diff --git a/src/main/java/org/olat/restapi/support/Ping.java b/src/main/java/org/olat/restapi/support/Ping.java
index 122ef4d22f5..6f89f6e97e1 100644
--- a/src/main/java/org/olat/restapi/support/Ping.java
+++ b/src/main/java/org/olat/restapi/support/Ping.java
@@ -27,6 +27,8 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * Description:<br>
@@ -36,6 +38,7 @@ import javax.ws.rs.core.Response;
  * Initial Date:  7 apr. 2010 <br>
  * @author srosse, stephane.rosse@frentix.com
  */
+@Tag(name = "Ping")
 @Path("ping")
 public class Ping {
 	
diff --git a/src/main/java/org/olat/restapi/system/OpenOLATStatisticsWebService.java b/src/main/java/org/olat/restapi/system/OpenOLATStatisticsWebService.java
index 7cc2d308bef..97f5ab48c75 100644
--- a/src/main/java/org/olat/restapi/system/OpenOLATStatisticsWebService.java
+++ b/src/main/java/org/olat/restapi/system/OpenOLATStatisticsWebService.java
@@ -48,6 +48,8 @@ import org.olat.restapi.system.vo.SessionsVO;
 import org.olat.restapi.system.vo.TasksVO;
 import org.olat.restapi.system.vo.UserStatisticsVO;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
@@ -87,6 +89,7 @@ public class OpenOLATStatisticsWebService implements Sampler {
 	 * @param request The HTTP request
 	 * @return The statistics about OpenOLAT users
 	 */
+	@Tag(name = "Users")
 	@GET
 	@Path("users")
 	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
@@ -105,6 +108,7 @@ public class OpenOLATStatisticsWebService implements Sampler {
 	 * @param request The HTTP request
 	 * @return The statistics about the repository
 	 */
+	@Tag(name = "Repo")
 	@GET
 	@Path("repository")
 	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
diff --git a/src/main/java/org/olat/restapi/system/SystemWebService.java b/src/main/java/org/olat/restapi/system/SystemWebService.java
index 0bf1efd1730..3a60b0c90f9 100644
--- a/src/main/java/org/olat/restapi/system/SystemWebService.java
+++ b/src/main/java/org/olat/restapi/system/SystemWebService.java
@@ -45,6 +45,8 @@ import org.olat.restapi.system.vo.EnvironmentInformationsVO;
 import org.olat.restapi.system.vo.ReleaseInfosVO;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * <h3>Description:</h3>
@@ -52,6 +54,7 @@ import org.springframework.stereotype.Component;
  * Initial Date:  18 jun. 2010 <br>
  * @author srosse, stephane.rosse@frentix.com, www.frentix.com
  */
+@Tag(name = "System")
 @Path("system")
 @Component
 public class SystemWebService {
diff --git a/src/main/java/org/olat/user/restapi/OrganisationsWebService.java b/src/main/java/org/olat/user/restapi/OrganisationsWebService.java
index c188eb4d452..25973b132ae 100644
--- a/src/main/java/org/olat/user/restapi/OrganisationsWebService.java
+++ b/src/main/java/org/olat/user/restapi/OrganisationsWebService.java
@@ -61,12 +61,15 @@ import org.olat.restapi.support.vo.RepositoryEntryVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * Initial date: 14 mai 2018<br>
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
+@Tag(name = "Organisations")
 @Component
 @Path("organisations")
 public class OrganisationsWebService {
diff --git a/src/main/java/org/olat/user/restapi/RelationRolesWebService.java b/src/main/java/org/olat/user/restapi/RelationRolesWebService.java
index 873adc72e1a..72469c5366d 100644
--- a/src/main/java/org/olat/user/restapi/RelationRolesWebService.java
+++ b/src/main/java/org/olat/user/restapi/RelationRolesWebService.java
@@ -46,12 +46,15 @@ import org.olat.restapi.security.RestSecurityHelper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * 
  * Initial date: 31 janv. 2019<br>
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
+@Tag(name = "Users")
 @Component
 @Path("users/relations")
 public class RelationRolesWebService {
diff --git a/src/main/java/org/olat/user/restapi/UserAuthenticationWebService.java b/src/main/java/org/olat/user/restapi/UserAuthenticationWebService.java
index 9a4f6ed2b7e..ee29e8c124b 100644
--- a/src/main/java/org/olat/user/restapi/UserAuthenticationWebService.java
+++ b/src/main/java/org/olat/user/restapi/UserAuthenticationWebService.java
@@ -53,11 +53,14 @@ import org.olat.restapi.support.vo.ErrorVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * This web service handles functionalities related to authentication credentials of users.
  * 
  * @author srosse, stephane.rosse@frentix.com
  */
+@Tag(name = "Users")
 @Component
 @Path("users/{username}/auth")
 public class UserAuthenticationWebService {
diff --git a/src/main/java/org/olat/user/restapi/UserWebService.java b/src/main/java/org/olat/user/restapi/UserWebService.java
index 1ceebfc9738..2159fcfcac4 100644
--- a/src/main/java/org/olat/user/restapi/UserWebService.java
+++ b/src/main/java/org/olat/user/restapi/UserWebService.java
@@ -94,11 +94,15 @@ import org.olat.user.propertyhandlers.UserPropertyHandler;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import io.swagger.v3.oas.annotations.tags.Tag;
+
 /**
  * This web service handles functionalities related to <code>User</code>.
  * 
  * @author srosse, stephane.rosse@frentix.com
  */
+
+@Tag (name = "Users")
 @Path("users")
 @Component
 public class UserWebService {
diff --git a/src/test/java/org/olat/restapi/DataGenerator.java b/src/test/java/org/olat/restapi/DataGenerator.java
new file mode 100644
index 00000000000..e69de29bb2d
-- 
GitLab