From c7dac598ed94741b2c9119f3d2942643954b473e Mon Sep 17 00:00:00 2001
From: srosse <stephane.rosse@frentix.com>
Date: Wed, 23 Jan 2019 14:38:14 +0100
Subject: [PATCH] OO-3831: add a column identifier in the calendars list

---
 .../calendar/_i18n/LocalStrings_de.properties |   1 +
 .../calendar/_i18n/LocalStrings_en.properties |   1 +
 .../calendar/_i18n/LocalStrings_fr.properties |   1 +
 .../manager/ICalFileCalendarManager.java      | 304 ++++++++----------
 ...lendarPersonalConfigurationController.java |  16 +-
 ...alendarPersonalConfigurationDataModel.java |  22 +-
 .../ui/CalendarPersonalConfigurationRow.java  |   4 +
 .../ui/components/KalendarRenderWrapper.java  |  18 +-
 .../java/org/olat/group/BusinessGroup.java    |   2 +-
 .../manager/ICalFileCalendarManagerTest.java  |   8 +-
 10 files changed, 187 insertions(+), 190 deletions(-)

diff --git a/src/main/java/org/olat/commons/calendar/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/commons/calendar/_i18n/LocalStrings_de.properties
index ff9f17ec802..9e750e22249 100644
--- a/src/main/java/org/olat/commons/calendar/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/commons/calendar/_i18n/LocalStrings_de.properties
@@ -211,6 +211,7 @@ table.add=+
 table.delete=-
 table.header.aggregated.feed=Aggregiert
 table.header.color=Farbe
+table.header.identifier=Kennzeichen
 table.header.name=Name
 table.header.tools=<i class\="o_icon o_icon-lg o_icon_actions"> </i>
 table.header.type=Typ
diff --git a/src/main/java/org/olat/commons/calendar/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/commons/calendar/_i18n/LocalStrings_en.properties
index 8f5932e2838..a453664777b 100644
--- a/src/main/java/org/olat/commons/calendar/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/commons/calendar/_i18n/LocalStrings_en.properties
@@ -257,6 +257,7 @@ table.add=+
 table.delete=-
 table.header.aggregated.feed=Aggregated
 table.header.color=Color
+table.header.identifier=Identifier
 table.header.name=Name
 table.header.tools=<i class\="o_icon o_icon-lg o_icon_actions"> </i>
 table.header.type=Type
diff --git a/src/main/java/org/olat/commons/calendar/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/commons/calendar/_i18n/LocalStrings_fr.properties
index 7e757d8befb..7dc0e9d5af4 100644
--- a/src/main/java/org/olat/commons/calendar/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/commons/calendar/_i18n/LocalStrings_fr.properties
@@ -211,6 +211,7 @@ table.add=+
 table.delete=-
 table.header.aggregated.feed=Agr\u00E9g\u00E9
 table.header.color=Couleur
+table.header.identifier=Identifiant
 table.header.name=Nom
 table.header.tools=<i class\="o_icon o_icon-lg o_icon_actions"> </i>
 table.header.type=Type
diff --git a/src/main/java/org/olat/commons/calendar/manager/ICalFileCalendarManager.java b/src/main/java/org/olat/commons/calendar/manager/ICalFileCalendarManager.java
index 610ad116843..0fef59773f7 100644
--- a/src/main/java/org/olat/commons/calendar/manager/ICalFileCalendarManager.java
+++ b/src/main/java/org/olat/commons/calendar/manager/ICalFileCalendarManager.java
@@ -69,12 +69,10 @@ import org.olat.core.logging.OLATRuntimeException;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.CodeHelper;
-import org.olat.core.util.FileUtils;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.WebappHelper;
 import org.olat.core.util.cache.CacheWrapper;
 import org.olat.core.util.coordinate.CoordinatorManager;
-import org.olat.core.util.coordinate.SyncerCallback;
 import org.olat.core.util.resource.OresHelper;
 import org.olat.course.ICourse;
 import org.olat.group.BusinessGroup;
@@ -301,47 +299,44 @@ public class ICalFileCalendarManager implements CalendarManager, InitializingBea
 			String targetId = "-" + targetCalendar.getType() + "-" + targetCalendar.getCalendarID() + "-";
 			
 			OLATResourceable calOres = getOresHelperFor(targetCalendar);
-			Boolean updatedSuccessful = CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync( calOres, new SyncerCallback<Boolean>() {
-				@Override
-				public Boolean execute() {
-					//remove event in target calendar which doesn't exist in stream
-					Collection<KalendarEvent> currentEvents = targetCalendar.getEvents();
-					for(KalendarEvent currentEvent:currentEvents) {
-						if(currentEvent.getExternalSource() != null && source.equals(currentEvent.getExternalSource())) {
-							String eventId = currentEvent.getID();
-							String recurrenceId = currentEvent.getRecurrenceID();
-							if(inTmpKalendar.getEvent(eventId, recurrenceId) == null) {
-								targetCalendar.removeEvent(currentEvent);
-							} else if(eventId.contains(targetId)) {
-								targetCalendar.removeEvent(currentEvent);//don't import myself;
-							}
+			Boolean updatedSuccessful = CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync( calOres, () -> {
+				//remove event in target calendar which doesn't exist in stream
+				Collection<KalendarEvent> currentEvents = targetCalendar.getEvents();
+				for(KalendarEvent currentEvent:currentEvents) {
+					if(currentEvent.getExternalSource() != null && source.equals(currentEvent.getExternalSource())) {
+						String eventId = currentEvent.getID();
+						String recurrenceId = currentEvent.getRecurrenceID();
+						if(inTmpKalendar.getEvent(eventId, recurrenceId) == null) {
+							targetCalendar.removeEvent(currentEvent);
+						} else if(eventId.contains(targetId)) {
+							targetCalendar.removeEvent(currentEvent);//don't import myself;
 						}
 					}
+				}
 
-					Collection<KalendarEvent> inEvents = inTmpKalendar.getEvents();
-					for(KalendarEvent inEvent:inEvents) {
-						if(inEvent.getID().contains(targetId)) {
-							continue;
-						}
-
-						inEvent.setManagedFlags(new CalendarManagedFlag[]{ CalendarManagedFlag.all } );
-						inEvent.setExternalSource(source);
-						
-						KalendarEvent currentEvent = targetCalendar.getEvent(inEvent.getID(), inEvent.getRecurrenceID());
-						if(currentEvent == null) {
-							targetCalendar.addEvent(inEvent);
-						} else {
-							//need perhaps more refined synchronization per event
-							targetCalendar.addEvent(inEvent);
-						}
+				Collection<KalendarEvent> inEvents = inTmpKalendar.getEvents();
+				for(KalendarEvent inEvent:inEvents) {
+					if(inEvent.getID().contains(targetId)) {
+						continue;
 					}
+
+					inEvent.setManagedFlags(new CalendarManagedFlag[]{ CalendarManagedFlag.all } );
+					inEvent.setExternalSource(source);
 					
-					boolean successfullyPersist = persistCalendar(targetCalendar);
-					// inform all controller about calendar change for reload
-					CoordinatorManager.getInstance().getCoordinator().getEventBus()
-						.fireEventToListenersOf(new CalendarGUIModifiedEvent(targetCalendar), OresHelper.lookupType(CalendarManager.class));
-					return new Boolean(successfullyPersist);
+					KalendarEvent currentEvent = targetCalendar.getEvent(inEvent.getID(), inEvent.getRecurrenceID());
+					if(currentEvent == null) {
+						targetCalendar.addEvent(inEvent);
+					} else {
+						//need perhaps more refined synchronization per event
+						targetCalendar.addEvent(inEvent);
+					}
 				}
+				
+				boolean successfullyPersist = persistCalendar(targetCalendar);
+				// inform all controller about calendar change for reload
+				CoordinatorManager.getInstance().getCoordinator().getEventBus()
+					.fireEventToListenersOf(new CalendarGUIModifiedEvent(targetCalendar), OresHelper.lookupType(CalendarManager.class));
+				return Boolean.valueOf(successfullyPersist);
 			});
 			
 			return updatedSuccessful.booleanValue();
@@ -368,15 +363,12 @@ public class ICalFileCalendarManager implements CalendarManager, InitializingBea
 	
 	private boolean writeCalendarFile(Calendar calendar, String calType, String calId) {
 		File fKalendarFile = getCalendarFile(calType, calId);
-		OutputStream os = null;
-		try {
-			os = new BufferedOutputStream(new FileOutputStream(fKalendarFile, false));
+
+		try(OutputStream os = new BufferedOutputStream(new FileOutputStream(fKalendarFile, false))) {
 			CalendarOutputter calOut = new CalendarOutputter(false);
 			calOut.output(calendar, os);
 		} catch (Exception e) {
 			return false;
-		} finally {
-			FileUtils.closeSafely(os);
 		}
 		return true;
 	}
@@ -797,7 +789,7 @@ public class ICalFileCalendarManager implements CalendarManager, InitializingBea
 		
 		// links if any
 		PropertyList linkProperties = event.getProperties(ICAL_X_OLAT_LINK);
-		List<KalendarEventLink> kalendarEventLinks = new ArrayList<KalendarEventLink>();
+		List<KalendarEventLink> kalendarEventLinks = new ArrayList<>();
 		for (Iterator<?> iter = linkProperties.iterator(); iter.hasNext();) {
 			XProperty linkProperty = (XProperty) iter.next();
 			if (linkProperty != null) {
@@ -918,7 +910,7 @@ public class ICalFileCalendarManager implements CalendarManager, InitializingBea
 	public KalendarRenderWrapper getPersonalCalendar(Identity identity) {
 		Kalendar cal = getCalendar(CalendarManager.TYPE_USER, identity.getName());
 		String fullName = userManager.getUserDisplayName(identity);
-		KalendarRenderWrapper calendarWrapper = new KalendarRenderWrapper(cal, fullName);
+		KalendarRenderWrapper calendarWrapper = new KalendarRenderWrapper(cal, fullName, null);
 		calendarWrapper.setCssClass(KalendarRenderWrapper.CALENDAR_COLOR_BLUE);
 		calendarWrapper.setVisible(true);
 		return calendarWrapper;
@@ -927,7 +919,7 @@ public class ICalFileCalendarManager implements CalendarManager, InitializingBea
 	@Override
 	public KalendarRenderWrapper getImportedCalendar(Identity identity, String calendarId) {
 		Kalendar cal = getCalendar(CalendarManager.TYPE_USER, calendarId);
-		KalendarRenderWrapper calendarWrapper = new KalendarRenderWrapper(cal, calendarId);
+		KalendarRenderWrapper calendarWrapper = new KalendarRenderWrapper(cal, calendarId, null);
 		calendarWrapper.setCssClass(KalendarRenderWrapper.CALENDAR_COLOR_BLUE);
 		calendarWrapper.setVisible(true);
 		calendarWrapper.setImported(true);
@@ -937,7 +929,7 @@ public class ICalFileCalendarManager implements CalendarManager, InitializingBea
 	@Override
 	public KalendarRenderWrapper getGroupCalendar(BusinessGroup businessGroup) {
 		Kalendar cal = getCalendar(CalendarManager.TYPE_GROUP, businessGroup.getResourceableId().toString());
-		KalendarRenderWrapper calendarWrapper = new KalendarRenderWrapper(cal, businessGroup.getName());
+		KalendarRenderWrapper calendarWrapper = new KalendarRenderWrapper(cal, businessGroup.getName(), null);
 		calendarWrapper.setCssClass(KalendarRenderWrapper.CALENDAR_COLOR_ORANGE);
 		calendarWrapper.setVisible(true);
 		return calendarWrapper;
@@ -946,7 +938,8 @@ public class ICalFileCalendarManager implements CalendarManager, InitializingBea
 	@Override
 	public KalendarRenderWrapper getCourseCalendar(ICourse course) {
 		Kalendar cal = getCalendar(CalendarManager.TYPE_COURSE, course.getResourceableId().toString());
-		KalendarRenderWrapper calendarWrapper = new KalendarRenderWrapper(cal, course.getCourseTitle());
+		String externalRef = course.getCourseEnvironment().getCourseGroupManager().getCourseEntry().getExternalRef();
+		KalendarRenderWrapper calendarWrapper = new KalendarRenderWrapper(cal, course.getCourseTitle(), externalRef);
 		calendarWrapper.setCssClass(KalendarRenderWrapper.CALENDAR_COLOR_GREEN);
 		calendarWrapper.setVisible(true);
 		return calendarWrapper;
@@ -961,7 +954,7 @@ public class ICalFileCalendarManager implements CalendarManager, InitializingBea
 			type = CalendarManager.TYPE_GROUP;
 		}
 		Kalendar cal = getCalendar(type, resource.getResourceableId().toString());
-		KalendarRenderWrapper calendarWrapper = new KalendarRenderWrapper(cal, "To delete");
+		KalendarRenderWrapper calendarWrapper = new KalendarRenderWrapper(cal, "To delete", null);
 		calendarWrapper.setCssClass(KalendarRenderWrapper.CALENDAR_COLOR_GREEN);
 		calendarWrapper.setVisible(true);
 		return calendarWrapper;
@@ -995,52 +988,43 @@ public class ICalFileCalendarManager implements CalendarManager, InitializingBea
 	@Override
 	public boolean addEventTo(final Kalendar cal, final List<KalendarEvent> kalendarEvents) {
 		OLATResourceable calOres = getOresHelperFor(cal);
-		Boolean persistSuccessful = CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync( calOres, new SyncerCallback<Boolean>() {
-			@Override
-			public Boolean execute() {
-				Kalendar loadedCal = getCalendarFromCache(cal.getType(),cal.getCalendarID());
-				for(KalendarEvent kalendarEvent:kalendarEvents) {
-					loadedCal.addEvent(kalendarEvent);
-					kalendarEvent.resetImmutableDates();
-				}
-				boolean successfullyPersist = persistCalendar(loadedCal);
-				return new Boolean(successfullyPersist);
+		Boolean persistSuccessful = CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync( calOres, () -> {
+			Kalendar loadedCal = getCalendarFromCache(cal.getType(),cal.getCalendarID());
+			for(KalendarEvent kalendarEvent:kalendarEvents) {
+				loadedCal.addEvent(kalendarEvent);
+				kalendarEvent.resetImmutableDates();
 			}
+			boolean successfullyPersist = persistCalendar(loadedCal);
+			return Boolean.valueOf(successfullyPersist);
 		});
 		// inform all controller about calendar change for reload
 		CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(new CalendarGUIModifiedEvent(cal), OresHelper.lookupType(CalendarManager.class));
 		return persistSuccessful.booleanValue();
 	}
 
-	/**
-	 * @see org.olat.commons.calendar.CalendarManager#removeEventFrom(org.olat.commons.calendar.model.Kalendar, org.olat.commons.calendar.model.KalendarEvent)
-	 */
 	@Override
 	public boolean removeEventFrom(final Kalendar cal, final KalendarEvent kalendarEvent) {
 		OLATResourceable calOres = getOresHelperFor(cal);
-		Boolean removeSuccessful = CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync( calOres, new SyncerCallback<Boolean>() {
-			@Override
-			public Boolean execute() {
-				String uid = kalendarEvent.getID();
-				String recurrenceId = kalendarEvent.getRecurrenceID();
-				Kalendar loadedCal = getCalendarFromCache(cal.getType(), cal.getCalendarID());
-				if(StringHelper.containsNonWhitespace(recurrenceId)) {
-					loadedCal.removeEvent(kalendarEvent);
-					KalendarEvent rootEvent = loadedCal.getEvent(kalendarEvent.getID(), null);
-					if(rootEvent != null && kalendarEvent instanceof KalendarRecurEvent) {
-						Date recurrenceDate = ((KalendarRecurEvent)kalendarEvent).getOccurenceDate();
-						rootEvent.addRecurrenceExc(recurrenceDate);
-					}
-				} else {
-					for(KalendarEvent kEvent:loadedCal.getEvents()) {
-						if(uid.equals(kEvent.getID())) {
-							loadedCal.removeEvent(kEvent);
-						}
+		Boolean removeSuccessful = CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync( calOres, () -> {
+			String uid = kalendarEvent.getID();
+			String recurrenceId = kalendarEvent.getRecurrenceID();
+			Kalendar loadedCal = getCalendarFromCache(cal.getType(), cal.getCalendarID());
+			if(StringHelper.containsNonWhitespace(recurrenceId)) {
+				loadedCal.removeEvent(kalendarEvent);
+				KalendarEvent rootEvent = loadedCal.getEvent(kalendarEvent.getID(), null);
+				if(rootEvent != null && kalendarEvent instanceof KalendarRecurEvent) {
+					Date recurrenceDate = ((KalendarRecurEvent)kalendarEvent).getOccurenceDate();
+					rootEvent.addRecurrenceExc(recurrenceDate);
+				}
+			} else {
+				for(KalendarEvent kEvent:loadedCal.getEvents()) {
+					if(uid.equals(kEvent.getID())) {
+						loadedCal.removeEvent(kEvent);
 					}
 				}
-				boolean successfullyPersist = persistCalendar(loadedCal);
-				return new Boolean(successfullyPersist);
 			}
+			boolean successfullyPersist = persistCalendar(loadedCal);
+			return Boolean.valueOf(successfullyPersist);
 		});
 		// inform all controller about calendar change for reload
 		CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(new CalendarGUIModifiedEvent(cal), OresHelper.lookupType(CalendarManager.class));
@@ -1050,26 +1034,23 @@ public class ICalFileCalendarManager implements CalendarManager, InitializingBea
 	@Override
 	public boolean removeOccurenceOfEvent(final Kalendar cal, final KalendarRecurEvent kalendarEvent) {
 		OLATResourceable calOres = getOresHelperFor(cal);
-		Boolean removeSuccessful = CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync(calOres, new SyncerCallback<Boolean>() {
-			@Override
-			public Boolean execute() {
-				String uid = kalendarEvent.getID();
-				Date occurenceDate = kalendarEvent.getBegin();
-		
-				Kalendar loadedCal = getCalendarFromCache(cal.getType(), cal.getCalendarID());
-				KalendarEvent rootEvent = loadedCal.getEvent(kalendarEvent.getID(), null);
-				rootEvent.addRecurrenceExc(kalendarEvent.getBegin());
-				
-				for(KalendarEvent kEvent:loadedCal.getEvents()) {
-					if(uid.equals(kEvent.getID())
-							&& kEvent.getOccurenceDate() != null
-							&& occurenceDate.equals(kEvent.getOccurenceDate())) {
-						loadedCal.removeEvent(kEvent);
-					}
+		Boolean removeSuccessful = CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync(calOres, () -> {
+			String uid = kalendarEvent.getID();
+			Date occurenceDate = kalendarEvent.getBegin();
+	
+			Kalendar loadedCal = getCalendarFromCache(cal.getType(), cal.getCalendarID());
+			KalendarEvent rootEvent = loadedCal.getEvent(kalendarEvent.getID(), null);
+			rootEvent.addRecurrenceExc(kalendarEvent.getBegin());
+			
+			for(KalendarEvent kEvent:loadedCal.getEvents()) {
+				if(uid.equals(kEvent.getID())
+						&& kEvent.getOccurenceDate() != null
+						&& occurenceDate.equals(kEvent.getOccurenceDate())) {
+					loadedCal.removeEvent(kEvent);
 				}
-				boolean successfullyPersist = persistCalendar(loadedCal);
-				return new Boolean(successfullyPersist);
 			}
+			boolean successfullyPersist = persistCalendar(loadedCal);
+			return Boolean.valueOf(successfullyPersist);
 		});
 		// inform all controller about calendar change for reload
 		CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(new CalendarGUIModifiedEvent(cal), OresHelper.lookupType(CalendarManager.class));
@@ -1080,54 +1061,45 @@ public class ICalFileCalendarManager implements CalendarManager, InitializingBea
 	@Override
 	public boolean removeFutureOfEvent(Kalendar cal, KalendarRecurEvent kalendarEvent) {
 		OLATResourceable calOres = getOresHelperFor(cal);
-		Boolean removeSuccessful = CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync(calOres, new SyncerCallback<Boolean>() {
-			@Override
-			public Boolean execute() {
-				boolean successfullyPersist = false;
-				try {
-					String uid = kalendarEvent.getID();
-					Date occurenceDate = kalendarEvent.getOccurenceDate();
+		Boolean removeSuccessful = CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync(calOres, () -> {
+			boolean successfullyPersist = false;
+			try {
+				String uid = kalendarEvent.getID();
+				Date occurenceDate = kalendarEvent.getOccurenceDate();
 
-					Kalendar loadedCal = getCalendarFromCache(cal.getType(), cal.getCalendarID());
-					KalendarEvent rootEvent = loadedCal.getEvent(kalendarEvent.getID(), null);
-					String rRule = rootEvent.getRecurrenceRule();
-					
-					Recur recur = new Recur(rRule);
-					recur.setUntil(CalendarUtils.createDate(occurenceDate));
-					RRule rrule = new RRule(recur);
-					rootEvent.setRecurrenceRule(rrule.getValue());
-					
-					for(KalendarEvent kEvent:loadedCal.getEvents()) {
-						if(uid.equals(kEvent.getID())
-								&& StringHelper.containsNonWhitespace(kEvent.getRecurrenceID())
-								&& occurenceDate.before(kEvent.getBegin())) {
-							loadedCal.removeEvent(kEvent);
-						}
+				Kalendar loadedCal = getCalendarFromCache(cal.getType(), cal.getCalendarID());
+				KalendarEvent rootEvent = loadedCal.getEvent(kalendarEvent.getID(), null);
+				String rRule = rootEvent.getRecurrenceRule();
+				
+				Recur recur = new Recur(rRule);
+				recur.setUntil(CalendarUtils.createDate(occurenceDate));
+				RRule rrule = new RRule(recur);
+				rootEvent.setRecurrenceRule(rrule.getValue());
+				
+				for(KalendarEvent kEvent:loadedCal.getEvents()) {
+					if(uid.equals(kEvent.getID())
+							&& StringHelper.containsNonWhitespace(kEvent.getRecurrenceID())
+							&& occurenceDate.before(kEvent.getBegin())) {
+						loadedCal.removeEvent(kEvent);
 					}
-					
-					successfullyPersist = persistCalendar(loadedCal);
-				} catch (ParseException e) {
-					log.error("", e);
 				}
-				return new Boolean(successfullyPersist);
+				
+				successfullyPersist = persistCalendar(loadedCal);
+			} catch (ParseException e) {
+				log.error("", e);
 			}
+			return Boolean.valueOf(successfullyPersist);
 		});
 		// inform all controller about calendar change for reload
 		CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(new CalendarGUIModifiedEvent(cal), OresHelper.lookupType(CalendarManager.class));
 		return removeSuccessful.booleanValue();
 	}
 
-	/**
-	 * @see org.olat.commons.calendar.CalendarManager#updateEventFrom(org.olat.commons.calendar.model.Kalendar, org.olat.commons.calendar.model.KalendarEvent)
-	 */
 	@Override
 	public boolean updateEventFrom(final Kalendar cal, final KalendarEvent kalendarEvent) {
 		OLATResourceable calOres = getOresHelperFor(cal);
-		Boolean updatedSuccessful = CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync( calOres, new SyncerCallback<Boolean>() {
-			@Override
-			public Boolean execute() {
-				return updateEventAlreadyInSync(cal, kalendarEvent);
-			}
+		Boolean updatedSuccessful = CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync( calOres, () -> {
+			return updateEventAlreadyInSync(cal, kalendarEvent);
 		});
 		return updatedSuccessful.booleanValue();
     }
@@ -1135,19 +1107,16 @@ public class ICalFileCalendarManager implements CalendarManager, InitializingBea
 	@Override
 	public boolean updateEventsFrom(Kalendar cal, List<KalendarEvent> kalendarEvents) {
 		final OLATResourceable calOres = getOresHelperFor(cal);
-		Boolean updatedSuccessful = CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync( calOres, new SyncerCallback<Boolean>() {
-			@Override
-			public Boolean execute() {
-				Kalendar loadedCal = getCalendarFromCache(cal.getType(), cal.getCalendarID());
-				for(KalendarEvent kalendarEvent:kalendarEvents) {
-					loadedCal.removeEvent(kalendarEvent); // remove old event
-					loadedCal.addEvent(kalendarEvent); // add changed event
-				}
-				boolean successfullyPersist = persistCalendar(loadedCal);
-				// inform all controller about calendar change for reload
-				CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(new CalendarGUIModifiedEvent(cal), OresHelper.lookupType(CalendarManager.class));
-				return successfullyPersist;
+		Boolean updatedSuccessful = CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync( calOres, () -> {
+			Kalendar loadedCal = getCalendarFromCache(cal.getType(), cal.getCalendarID());
+			for(KalendarEvent kalendarEvent:kalendarEvents) {
+				loadedCal.removeEvent(kalendarEvent); // remove old event
+				loadedCal.addEvent(kalendarEvent); // add changed event
 			}
+			boolean successfullyPersist = persistCalendar(loadedCal);
+			// inform all controller about calendar change for reload
+			CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(new CalendarGUIModifiedEvent(cal), OresHelper.lookupType(CalendarManager.class));
+			return successfullyPersist;
 		});
 		return updatedSuccessful.booleanValue();
 	}
@@ -1236,32 +1205,29 @@ public class ICalFileCalendarManager implements CalendarManager, InitializingBea
 	@Override
 	public boolean updateCalendar(final Kalendar cal, final Kalendar importedCal) {
 		OLATResourceable calOres = getOresHelperFor(cal);
-		Boolean updatedSuccessful = CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync( calOres, new SyncerCallback<Boolean>() {
-			@Override
-			public Boolean execute() {
-				Map<KalendarEventKey,KalendarEvent> uidToEvent = new HashMap<>();
-				for(KalendarEvent event:cal.getEvents()) {
-					if(StringHelper.containsNonWhitespace(event.getID())) {
-						uidToEvent.put(new KalendarEventKey(event), event);
-					}
+		Boolean updatedSuccessful = CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync( calOres, () -> {
+			Map<KalendarEventKey,KalendarEvent> uidToEvent = new HashMap<>();
+			for(KalendarEvent event:cal.getEvents()) {
+				if(StringHelper.containsNonWhitespace(event.getID())) {
+					uidToEvent.put(new KalendarEventKey(event), event);
 				}
-				
-				Kalendar loadedCal = getCalendarFromCache(cal.getType(), cal.getCalendarID());
-				for(KalendarEvent importedEvent:importedCal.getEvents()) {
-					KalendarEventKey uid = new KalendarEventKey(importedEvent);
-					if(uidToEvent.containsKey(uid)) {
-						loadedCal.removeEvent(importedEvent); // remove old event
-						loadedCal.addEvent(importedEvent); // add changed event
-					} else {
-						loadedCal.addEvent(importedEvent);
-					}
+			}
+			
+			Kalendar loadedCal = getCalendarFromCache(cal.getType(), cal.getCalendarID());
+			for(KalendarEvent importedEvent:importedCal.getEvents()) {
+				KalendarEventKey uid = new KalendarEventKey(importedEvent);
+				if(uidToEvent.containsKey(uid)) {
+					loadedCal.removeEvent(importedEvent); // remove old event
+					loadedCal.addEvent(importedEvent); // add changed event
+				} else {
+					loadedCal.addEvent(importedEvent);
 				}
-				
-				boolean successfullyPersist = persistCalendar(cal);
-				// inform all controller about calendar change for reload
-				CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(new CalendarGUIModifiedEvent(cal), OresHelper.lookupType(CalendarManager.class));
-				return new Boolean(successfullyPersist);
 			}
+			
+			boolean successfullyPersist = persistCalendar(cal);
+			// inform all controller about calendar change for reload
+			CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(new CalendarGUIModifiedEvent(cal), OresHelper.lookupType(CalendarManager.class));
+			return Boolean.valueOf(successfullyPersist);
 		});
 		return updatedSuccessful.booleanValue();
 	}
diff --git a/src/main/java/org/olat/commons/calendar/ui/CalendarPersonalConfigurationController.java b/src/main/java/org/olat/commons/calendar/ui/CalendarPersonalConfigurationController.java
index cdab212d876..dca744ab459 100644
--- a/src/main/java/org/olat/commons/calendar/ui/CalendarPersonalConfigurationController.java
+++ b/src/main/java/org/olat/commons/calendar/ui/CalendarPersonalConfigurationController.java
@@ -113,16 +113,12 @@ public class CalendarPersonalConfigurationController extends FormBasicController
 		
 		//add the table
 		FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel();
-		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ConfigCols.type.i18nKey(), ConfigCols.type.ordinal(),
-				true, ConfigCols.type.name(), new CalendarTypeClassRenderer()));
-		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ConfigCols.cssClass.i18nKey(), ConfigCols.cssClass.ordinal(),
-				true, ConfigCols.cssClass.name()));
-		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ConfigCols.name.i18nKey(), ConfigCols.name.ordinal(),
-				true, ConfigCols.name.name()));
-		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ConfigCols.visible.i18nKey(), ConfigCols.visible.ordinal(),
-				true, ConfigCols.visible.name()));
-		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ConfigCols.aggregated.i18nKey(), ConfigCols.aggregated.ordinal(),
-				true, ConfigCols.aggregated.name()));
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ConfigCols.type, new CalendarTypeClassRenderer()));
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ConfigCols.cssClass));
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ConfigCols.name));
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ConfigCols.identifier));
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ConfigCols.visible));
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ConfigCols.aggregated));
 		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ConfigCols.feed.i18nKey(), ConfigCols.feed.ordinal()));
 		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ConfigCols.tools.i18nKey(), ConfigCols.tools.ordinal()));
 		
diff --git a/src/main/java/org/olat/commons/calendar/ui/CalendarPersonalConfigurationDataModel.java b/src/main/java/org/olat/commons/calendar/ui/CalendarPersonalConfigurationDataModel.java
index 6f03e7ec582..f87558b69c9 100644
--- a/src/main/java/org/olat/commons/calendar/ui/CalendarPersonalConfigurationDataModel.java
+++ b/src/main/java/org/olat/commons/calendar/ui/CalendarPersonalConfigurationDataModel.java
@@ -23,6 +23,7 @@ import java.util.List;
 
 import org.olat.core.commons.persistence.SortKey;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiTableDataModel;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiSortableColumnDef;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.SortableFlexiTableDataModel;
 
@@ -63,7 +64,8 @@ public class CalendarPersonalConfigurationDataModel extends DefaultFlexiTableDat
 		switch(ConfigCols.values()[col]) {
 			case type: return row.getWrapper();
 			case name: return row.getDisplayName();
-			case cssClass: return row.getColorLink();//.getCssClass();
+			case identifier: return row.getIdentifier();
+			case cssClass: return row.getColorLink();
 			case visible: return row.getVisibleLink();
 			case aggregated: return row.getAggregatedLink();
 			case feed: return row.getFeedLink();
@@ -72,9 +74,10 @@ public class CalendarPersonalConfigurationDataModel extends DefaultFlexiTableDat
 		return null;
 	}
 	
-	public enum ConfigCols {
+	public enum ConfigCols implements FlexiSortableColumnDef {
 		type("table.header.type"),
 		name("table.header.name"),
+		identifier("table.header.identifier"),
 		cssClass("table.header.color"),
 		visible("table.header.visible"),
 		aggregated("table.header.aggregated.feed"),
@@ -90,5 +93,20 @@ public class CalendarPersonalConfigurationDataModel extends DefaultFlexiTableDat
 		public String i18nKey() {
 			return i18nKey;
 		}
+
+		@Override
+		public String i18nHeaderKey() {
+			return i18nKey;
+		}
+
+		@Override
+		public boolean sortable() {
+			return this != tools && this != feed;
+		}
+
+		@Override
+		public String sortKey() {
+			return name();
+		}
 	}
 }
diff --git a/src/main/java/org/olat/commons/calendar/ui/CalendarPersonalConfigurationRow.java b/src/main/java/org/olat/commons/calendar/ui/CalendarPersonalConfigurationRow.java
index ab97330b3b6..30a08b40792 100644
--- a/src/main/java/org/olat/commons/calendar/ui/CalendarPersonalConfigurationRow.java
+++ b/src/main/java/org/olat/commons/calendar/ui/CalendarPersonalConfigurationRow.java
@@ -64,6 +64,10 @@ public class CalendarPersonalConfigurationRow {
 	public String getDisplayName() {
 		return wrapper.getDisplayName();
 	}
+	
+	public String getIdentifier() {
+		return wrapper.getIdentifier();
+	}
 
 	public String getCssClass() {
 		return wrapper.getCssClass();
diff --git a/src/main/java/org/olat/commons/calendar/ui/components/KalendarRenderWrapper.java b/src/main/java/org/olat/commons/calendar/ui/components/KalendarRenderWrapper.java
index 38ffdec99ba..85042d73f6b 100644
--- a/src/main/java/org/olat/commons/calendar/ui/components/KalendarRenderWrapper.java
+++ b/src/main/java/org/olat/commons/calendar/ui/components/KalendarRenderWrapper.java
@@ -55,6 +55,7 @@ public class KalendarRenderWrapper {
 	public static final int ACCESS_READ_ONLY = 1;
 	
 	private String displayName;
+	private String identifier;
 	
 	private Kalendar kalendar;
 	private LinkProvider linkProvider;
@@ -76,15 +77,14 @@ public class KalendarRenderWrapper {
 	 * @param calendarColor
 	 * @param access
 	 */
-	public KalendarRenderWrapper(Kalendar kalendar, String displayName) {
-		this.kalendar = kalendar;
-		this.displayName = displayName;
-		setConfiguration(null);
+	public KalendarRenderWrapper(Kalendar kalendar, String displayName, String identifier) {
+		this(kalendar, null, displayName, identifier);
 	}
 	
-	public KalendarRenderWrapper(Kalendar kalendar, CalendarUserConfiguration config, String displayName) {
+	public KalendarRenderWrapper(Kalendar kalendar, CalendarUserConfiguration config, String displayName, String identifier) {
 		this.kalendar = kalendar;
 		this.displayName = displayName;
+		this.identifier = identifier;
 		setConfiguration(config);
 	}
 	
@@ -115,6 +115,14 @@ public class KalendarRenderWrapper {
 		this.displayName = displayName;
 	}
 
+	public String getIdentifier() {
+		return identifier;
+	}
+
+	public void setIdentifier(String identifier) {
+		this.identifier = identifier;
+	}
+
 	public int getAccess() {
 		return access;
 	}
diff --git a/src/main/java/org/olat/group/BusinessGroup.java b/src/main/java/org/olat/group/BusinessGroup.java
index 878b94587ce..f2e64e790b4 100644
--- a/src/main/java/org/olat/group/BusinessGroup.java
+++ b/src/main/java/org/olat/group/BusinessGroup.java
@@ -45,7 +45,7 @@ public interface BusinessGroup extends BusinessGroupShort, Persistable, CreateIn
 
 	/** regular expression to check for valid group names */
 	// commas are not allowed. name is used in course conditions for weak binding
-	public final static String VALID_GROUPNAME_REGEXP = "^[^,\"]*$";
+	public static final String VALID_GROUPNAME_REGEXP = "^[^,\"]*$";
 	
 	/** the max length for the group name.*/
 	public static final int MAX_GROUP_NAME_LENGTH = 255;
diff --git a/src/test/java/org/olat/commons/calendar/manager/ICalFileCalendarManagerTest.java b/src/test/java/org/olat/commons/calendar/manager/ICalFileCalendarManagerTest.java
index 8eeec6bbd9c..8e7001ee2a1 100644
--- a/src/test/java/org/olat/commons/calendar/manager/ICalFileCalendarManagerTest.java
+++ b/src/test/java/org/olat/commons/calendar/manager/ICalFileCalendarManagerTest.java
@@ -52,7 +52,6 @@ import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.commons.io.FileUtils;
-import org.infinispan.manager.EmbeddedCacheManager;
 import org.junit.Assert;
 import org.junit.Assume;
 import org.junit.Test;
@@ -89,8 +88,7 @@ public class ICalFileCalendarManagerTest extends OlatTestCase {
 	private final void emptyCalendarCache() {
 		CoordinatorManager coordinator = CoreSpringFactory.getImpl(CoordinatorManager.class);
 		Cacher cacher = coordinator.getCoordinator().getCacher();
-		EmbeddedCacheManager cm = cacher.getCacheContainer();
-		cm.getCache("CalendarManager@calendar").clear();
+		cacher.getCacheContainer().getCache("CalendarManager@calendar").clear();
 	}
 	
 	@Test
@@ -328,6 +326,8 @@ public class ICalFileCalendarManagerTest extends OlatTestCase {
 		File newCalendarFile = new File(calendarFile.getParentFile(), calendarFile.getName());
 		InputStream in = CalendarImportTest.class.getResourceAsStream("cal_without_dtend.ics");
 		FileUtils.copyInputStreamToFile(in, newCalendarFile);
+		in.close();
+		
 		//to be sure
 		emptyCalendarCache();
 		//load the calendar
@@ -474,6 +474,8 @@ public class ICalFileCalendarManagerTest extends OlatTestCase {
 		File newCalendarFile = new File(calendarFile.getParentFile(), calendarFile.getName());
 		InputStream in = CalendarImportTest.class.getResourceAsStream("cal_without_dtend.ics");
 		FileUtils.copyInputStreamToFile(in, newCalendarFile);
+		in.close();
+		
 		//to be sure
 		emptyCalendarCache();
 		//load the calendar
-- 
GitLab