From 5867ac3bb70db38d3d60e6e3ae7c3e8a229bf721 Mon Sep 17 00:00:00 2001
From: Daniel Haag <daniel.haag@uibk.ac.at>
Date: Fri, 30 Aug 2019 14:07:12 +0200
Subject: [PATCH] openolat#82: reimplementation of the vle-connect connection

---
 pom.xml                                       |   5 +
 .../uibk/course/_spring/uibkCourseContext.xml |   2 +
 .../java/at/ac/uibk/sis/SisManagerImpl.java   |  71 +++---------
 .../vleconnect/cxf/jaxrs/OlatService.java     | 106 ++++++++++++++++++
 .../uibk/vleconnect/cxf/jaxrs/SisService.java |  96 ++++++++++++++++
 .../resources/serviceconfig/olat.properties   |   3 +
 6 files changed, 227 insertions(+), 56 deletions(-)
 create mode 100644 src/main/java/at/ac/uibk/vleconnect/cxf/jaxrs/OlatService.java
 create mode 100644 src/main/java/at/ac/uibk/vleconnect/cxf/jaxrs/SisService.java

diff --git a/pom.xml b/pom.xml
index c9fc80d2963..6b0b2463d98 100644
--- a/pom.xml
+++ b/pom.xml
@@ -435,6 +435,11 @@
 				    <artifactId>cxf-rt-rs-service-description-openapi-v3</artifactId>
 				    <version>${apache.cxf}</version>
 				</dependency>
+				<dependency>
+				    <groupId>org.apache.cxf</groupId>
+				    <artifactId>cxf-rt-rs-client</artifactId>
+				    <version>${apache.cxf}</version>
+				</dependency>
 				<dependency>
 				    <groupId>org.webjars</groupId>
 				    <artifactId>swagger-ui</artifactId>
diff --git a/src/main/java/at/ac/uibk/course/_spring/uibkCourseContext.xml b/src/main/java/at/ac/uibk/course/_spring/uibkCourseContext.xml
index 1debc87865e..b618ac3377f 100644
--- a/src/main/java/at/ac/uibk/course/_spring/uibkCourseContext.xml
+++ b/src/main/java/at/ac/uibk/course/_spring/uibkCourseContext.xml
@@ -16,6 +16,8 @@
 		<property name="contextPath" value="${course.wizard.sismanager.contextPath}" />
 		<property name="visibleTerms" value="${course.wizard.sismanager.visibleTerms}" />
 		<property name="defaultTerm" value="${course.wizard.sismanager.defaultTerm}" />
+		<property name="serviceUsername" value="${course.wizard.sismanager.username}" />
+		<property name="servicePassword" value="${course.wizard.sismanager.password}" />
 	</bean>
 	<bean id="at.ac.uibk.course.model.CreateCourseConfiguration" class="at.ac.uibk.course.model.CreateCourseConfiguration" lazy-init="true" scope="prototype">
 		<property name="sendEmail" value="true" />
diff --git a/src/main/java/at/ac/uibk/sis/SisManagerImpl.java b/src/main/java/at/ac/uibk/sis/SisManagerImpl.java
index c66e2aa468d..4b1f2e5ab54 100644
--- a/src/main/java/at/ac/uibk/sis/SisManagerImpl.java
+++ b/src/main/java/at/ac/uibk/sis/SisManagerImpl.java
@@ -20,24 +20,15 @@
 
 package at.ac.uibk.sis;
 
-import java.net.URI;
-import java.util.Map;
-
-import javax.xml.bind.JAXBContext;
-import javax.xml.namespace.QName;
-import javax.xml.transform.Source;
-import javax.xml.transform.stream.StreamSource;
-import javax.xml.ws.Dispatch;
-import javax.xml.ws.Service;
-import javax.xml.ws.handler.MessageContext;
-import javax.xml.ws.http.HTTPBinding;
-
-import org.olat.core.id.Identity;
+import org.apache.cxf.jaxrs.client.JAXRSClientFactory;
 import org.apache.logging.log4j.Logger;
+import org.olat.core.id.Identity;
 import org.olat.core.logging.Tracing;
 
 import at.ac.uibk.course.model.SisCourse;
 import at.ac.uibk.course.model.SisCourses;
+import at.ac.uibk.vleconnect.cxf.jaxrs.OlatService;
+import at.ac.uibk.vleconnect.cxf.jaxrs.SisService;
 
 /**
  * Initial Date: May 30, 2016
@@ -49,59 +40,27 @@ public class SisManagerImpl extends SisManager {
 
 	private static final Logger log = Tracing.createLoggerFor(SisManager.class);
 	
-	@SuppressWarnings("rawtypes")
-	private Object runSisRequest(Class returnClass, final String httpMethod, final String urlPath, final String query) throws SisManagerException {
-		try {
-			// create service
-			final URI nsURI = new URI("urn:sis:at");
-			final QName serviceName = new QName("sis", nsURI.toString());
-			final QName portName = new QName("sis_port", nsURI.toString());
-			final Service service = Service.create(serviceName);
-			final String absoluteUrlPath = getContextPath() + urlPath;
-
-			
-			final URI address = new URI(scheme, null, host, port, absoluteUrlPath, query, null);
-			service.addPort(portName, HTTPBinding.HTTP_BINDING, address.toString());
-			// send request
-			if (returnClass != null) {
-				final JAXBContext jbc = JAXBContext.newInstance(returnClass);
-				final Dispatch<Object> d = service.createDispatch(portName, jbc, Service.Mode.PAYLOAD);
-				final Map<String, Object> requestContext = d.getRequestContext();
-				requestContext.put(MessageContext.HTTP_REQUEST_METHOD, new String(httpMethod));
-				// invoke
-				return d.invoke(returnClass.newInstance());
-			} else {
-				final Dispatch<Source> d = service.createDispatch(portName, Source.class, Service.Mode.PAYLOAD);
-				final Map<String, Object> requestContext = d.getRequestContext();
-				requestContext.put(MessageContext.HTTP_REQUEST_METHOD, new String(httpMethod));
-				// invoke
-				Source request = new StreamSource();
-				return d.invokeAsync(request);
-			}
-		} catch (final Exception ex) {
-			log.error("Cannot execute SIS request.", ex);
-			throw new SisManagerException("Error executing SIS request: " + ex.getMessage(),ex);
-		}
-
-	}
-	
-	
 	@Override
 	public SisCourses findCourses(final Identity identity, final String searchTerm) throws SisManagerException {
-		final String search = searchTerm.replace('*', '%');
-		return (SisCourses) runSisRequest(SisCourses.class, "GET", "/sis/courses/find","terms=" + getVisibleTerms() +
-				(identity != null ? "&username=" + identity.getName():"") +
-				(searchTerm.length() > 0 ? "&title=" + search:""));
+		SisService sisService = JAXRSClientFactory.create(scheme + "://" + host + ":" + port + contextPath + "/sis",
+				SisService.class, serviceUsername, servicePassword, null);
+		return sisService.findSisCourses(getVisibleTerms(),
+				searchTerm.replace('*', '%'), null,
+				(identity != null ? identity.getName():"*"), "20");
 	}
 
 	@Override
 	public SisCourse getCourse(final String externalId) throws SisManagerException {
-		return (SisCourse) runSisRequest(SisCourse.class, "GET", "/sis/courses/" + externalId,null);
+		SisService sisService = JAXRSClientFactory.create(scheme + "://" + host + ":" + port + contextPath + "/sis",
+				SisService.class, serviceUsername, servicePassword, null);
+		return sisService.getSisCourse(externalId);
 	}
 
 	@Override
 	public void sendInvalidateCourseEvent(String externalId) {
-		runSisRequest(null, "GET", "/olat/courses/" + externalId + "/invalidate",null);
+		OlatService olatService = JAXRSClientFactory.create(scheme + "://" + host + ":" + port + contextPath + "/olat",
+				OlatService.class, serviceUsername, servicePassword, null);
+		olatService.invalidateOlatCourse(externalId);
 	}
 
 }
diff --git a/src/main/java/at/ac/uibk/vleconnect/cxf/jaxrs/OlatService.java b/src/main/java/at/ac/uibk/vleconnect/cxf/jaxrs/OlatService.java
new file mode 100644
index 00000000000..4b17cf0d202
--- /dev/null
+++ b/src/main/java/at/ac/uibk/vleconnect/cxf/jaxrs/OlatService.java
@@ -0,0 +1,106 @@
+package at.ac.uibk.vleconnect.cxf.jaxrs;
+
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.Produces;
+
+@Path("/")
+@Produces("application/xml")
+public interface OlatService {
+
+	@GET
+	@Path("/courses/invalidate")
+	public String invalidateOlatCourses(
+			@DefaultValue("all") @QueryParam("terms") String terms);
+	
+	@GET
+	@Path("/courses/remove_duplicates")
+	public String removeDuplicateCourses();
+
+	@GET
+	@Path("/courses/{externalCourseId}")
+	public String getOlatCourseByExternalId(@PathParam("externalCourseId") String externalCourseId);
+
+	@GET
+	@Path("/groups/{olatGroupKey}/{olatGroupMembershipType}")
+	public String getOlatGroupMembers(@PathParam("olatGroupKey") String olatGroupKey,
+			@PathParam("olatGroupMembershipType") String olatGroupMembershipType);
+	
+	
+	@GET
+	@Path("/courses/{externalCourseId}/invalidate")
+	@Produces("text/plain")
+	public String invalidateOlatCourse(@PathParam("externalCourseId") String externalCourseId);
+
+	@GET
+	@Path("/repo/entries/{olatRepositoryEntryKey}")
+	public String getOlatRepositoryEntry(@PathParam("olatRepositoryEntryKey") String olatRepositoryEntryKey);
+
+	@GET
+	@Path("/repo/entries/{olatRepositoryEntryKey}/linkTo/{externalCourseId}")
+	public String linkOlatRepositoryEntry(@PathParam("externalCourseId") String externalCourseId,
+			@PathParam("olatRepositoryEntryKey") String olatRepositoryEntryKey,
+			@DefaultValue("#none#") @QueryParam("olatManagedFlags") String olatManagedFlags);
+
+	@GET
+	@Path("/repo/entries/{olatRepositoryEntryKey}/updateFlags")
+	public String updateOlatRepositoryEntryManagedFlags(@PathParam("olatRepositoryEntryKey") String olatRepositoryEntryKey,
+			@DefaultValue("#none#") @QueryParam("olatManagedFlags") String olatManagedFlags);
+
+	@GET
+	@Path("/users/invalidate")
+	@Produces("text/plain")
+	public String invalidateOlatUsers();
+	
+
+	@GET
+	@Path("/users/modified/invalidate")
+	@Produces("text/plain")
+	public String invalidateOlatUsersModified(@QueryParam("modifiedSince") String modifiedSince);
+
+	@GET
+	@Path("/users/differing/invalidate")
+	@Produces("text/plain")
+	public String invalidateOlatUsersDiffering();
+	
+	@GET
+	@Path("/users/{userLogin}")
+	public String getOlatUser(@PathParam("userLogin") String userLogin);
+
+	@GET
+	@Path("/users/find/{userLogin}")
+	public String findOlatUser(@PathParam("userLogin") String userLogin);
+
+	@GET
+	@Path("/users/{userLogin}/invalidate")
+	@Produces("text/plain")
+	public String invalidateOlatUser(
+			@PathParam("userLogin") String userLogin);
+
+	@GET
+	@Path("/users/{userLogin}/purge_preliminary_deleted")
+	@Produces("text/plain")
+	public String purgePreliminaryDeletedOlatUser(
+			@PathParam("userLogin") String userLogin);
+	
+	@PUT
+	@Path("/users/{userLogin}/roles/author")
+	public String setOlatUserAuthorRole(
+			@PathParam("userLogin") String userLogin);
+
+	@PUT
+	@Path("/users/{userLogin}/status/set")
+	public String setOlatUserStatus(
+			@PathParam("userLogin") String userLogin,
+			@QueryParam("olatUserStatusNumber") String olatUserStatusNumber);
+
+	@PUT
+	@Path("/users/{userLogin}/status/sync")
+	public String syncOlatUserStatus(
+			@PathParam("userLogin") String userLogin);
+
+}
diff --git a/src/main/java/at/ac/uibk/vleconnect/cxf/jaxrs/SisService.java b/src/main/java/at/ac/uibk/vleconnect/cxf/jaxrs/SisService.java
new file mode 100644
index 00000000000..88b56bce95e
--- /dev/null
+++ b/src/main/java/at/ac/uibk/vleconnect/cxf/jaxrs/SisService.java
@@ -0,0 +1,96 @@
+package at.ac.uibk.vleconnect.cxf.jaxrs;
+
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+
+import at.ac.uibk.course.model.SisCourse;
+import at.ac.uibk.course.model.SisCourses;
+
+@Path("/")
+public interface SisService {
+
+	@GET
+	@Path("/users")
+	@Produces("application/xml")
+	public String getSisUsersWithAccount();
+
+	@GET
+	@Path("/users/modified")
+	@Produces("application/xml")
+	public String getSisUsersByModtime();
+
+	@GET
+	@Path("/users/{userLogin}")
+	@Produces("application/xml")
+	public String getSisUsersByAccount(@PathParam("userLogin") String userLogin);
+
+	@GET
+	@Path("/users/{userLogin}/coursesHeld")
+	@Produces("application/xml")
+	public String getSisCoursesHeld(@PathParam("userLogin") String userLogin,
+			@DefaultValue("all") @QueryParam("terms") String terms);
+
+	@GET
+	@Path("/users/{userLogin}/courses")
+	@Produces("application/xml")
+	public String findSisCoursesByUserAndTerms(@PathParam("userLogin") String userLogin,
+			@DefaultValue("all") @QueryParam("terms") String terms);
+
+	@GET
+	@Path("/users/find")
+	@Produces("application/xml")
+	public String findSisUsers(@QueryParam("givenName") String givenName,
+			@QueryParam("familyName") String familyName,
+			@QueryParam("uvwId") String uvwId);
+
+	@GET
+	@Path("/courses/{externalCourseId}")
+	@Produces("application/xml")
+	public SisCourse getSisCourse(@PathParam("externalCourseId") String externalCourseId);
+
+	@GET
+	@Path("/courses/{externalCourseId}/repositoryentry")
+	@Produces("application/xml")
+	public String getSisRepositoryEntry(@PathParam("externalCourseId") String externalCourseId);
+
+	@GET
+	@Path("/courses/find")
+	@Produces("application/xml")
+	SisCourses findSisCourses(
+			@DefaultValue("all") @QueryParam("terms") String terms,
+			@QueryParam("title") String title,
+			@DefaultValue("none") @QueryParam("number") String number,
+			@DefaultValue("*") @QueryParam("username") String username,
+			@DefaultValue("20") @QueryParam("limit") String limit);
+
+	@GET
+	@Path("/courses/{externalCourseId}/groups")
+	@Produces("application/xml")
+	public String getSisCourseGroups(@PathParam("externalCourseId") String externalCourseId);
+
+	@GET
+	@Path("/groups/{externalGroupId}")
+	@Produces("application/xml")
+	public String getSisGroup(@PathParam("externalGroupId") String externalGroupId);
+
+	@GET
+	@Path("/groups/{externalGroupId}/events")
+	@Produces("application/xml")
+	public String findSisEventsByGroup(@PathParam("externalGroupId") String externalGroupId);
+	
+	@GET
+	@Path("/groups/{externalGroupId}/elearningevents")
+	@Produces("application/xml")
+	public String findSisElearningEventsByGroup(@PathParam("externalGroupId") String externalGroupId);
+	
+	@GET
+	@Path("/ressources/{externalRessourceId}/bookings")
+	@Produces("application/xml")
+	public String findSisTvrBookingsByIdAfterDate(@PathParam("externalRessourceId") String externalRessourceId,
+			@DefaultValue("now") @QueryParam("bookingsAfterDate") String bookingsAfterDate);
+
+}
diff --git a/src/main/resources/serviceconfig/olat.properties b/src/main/resources/serviceconfig/olat.properties
index 1ed52a60ea6..f190e238fa0 100644
--- a/src/main/resources/serviceconfig/olat.properties
+++ b/src/main/resources/serviceconfig/olat.properties
@@ -1645,6 +1645,9 @@ course.wizard.sismanager.visibleTerms=2016W,2016S
 # The default term to show, 0 means the first in the list
 course.wizard.sismanager.defaultTerm=2016W
 
+course.wizard.sismanager.username=user
+course.wizard.sismanager.password=verysecret
+
 course.wizard.managedflags.autonomous=delete,copy
 course.wizard.managedflags.fullysynced=details,close,delete,bookings,copy
 course.wizard.managedflags.syncednoregistration=details,close,delete,copy 
-- 
GitLab