diff --git a/src/main/java/org/olat/core/gui/control/generic/iframe/IFrameDeliveryMapper.java b/src/main/java/org/olat/core/gui/control/generic/iframe/IFrameDeliveryMapper.java
index 26113e372c8f2bd8986ce82bbc309dd326de93fc..00438dc0f42ef80d0e241093c8d91382ccaf8ed9 100644
--- a/src/main/java/org/olat/core/gui/control/generic/iframe/IFrameDeliveryMapper.java
+++ b/src/main/java/org/olat/core/gui/control/generic/iframe/IFrameDeliveryMapper.java
@@ -22,11 +22,13 @@ package org.olat.core.gui.control.generic.iframe;
 import java.nio.charset.Charset;
 import java.nio.charset.IllegalCharsetNameException;
 import java.nio.charset.StandardCharsets;
+import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import javax.servlet.http.HttpServletRequest;
 
+import org.apache.logging.log4j.Logger;
 import org.olat.core.dispatcher.impl.StaticMediaDispatcher;
 import org.olat.core.dispatcher.mapper.Mapper;
 import org.olat.core.gui.components.htmlheader.jscss.CustomCSSDelegate;
@@ -34,15 +36,17 @@ import org.olat.core.gui.media.MediaResource;
 import org.olat.core.gui.media.NotFoundMediaResource;
 import org.olat.core.gui.media.StringMediaResource;
 import org.olat.core.gui.render.StringOutput;
-import org.apache.logging.log4j.Logger;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.FileUtils;
 import org.olat.core.util.SimpleHtmlParser;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.WebappHelper;
+import org.olat.core.util.vfs.VFSContainer;
 import org.olat.core.util.vfs.VFSItem;
 import org.olat.core.util.vfs.VFSLeaf;
+import org.olat.core.util.vfs.VFSManager;
 import org.olat.core.util.vfs.VFSMediaResource;
+import org.olat.core.util.vfs.filters.VFSItemFilter;
 
 /**
  * 
@@ -177,20 +181,14 @@ public class IFrameDeliveryMapper implements Mapper {
 	}
 
 	protected MediaResource deliverFile(HttpServletRequest httpRequest, String path, boolean isPopUp) {
-		MediaResource mr;
-		VFSLeaf vfsLeaf = null;
-		VFSItem vfsItem = null;
 		//if directory gets renamed root becomes null
 		if (rootDir == null) {
 			return new NotFoundMediaResource();
-		} else {
-			vfsItem = rootDir.resolve(path);
-		}
-		//only files are allowed, but somehow it happened that folders showed up here
-		if (vfsItem instanceof VFSLeaf) {
-			vfsLeaf = (VFSLeaf) rootDir.resolve(path);
-		}
+		} 
 		
+		VFSLeaf vfsLeaf = resolveFile(path);
+
+		MediaResource mr;
 		if (vfsLeaf == null) {
 			mr = new NotFoundMediaResource();
 		} else {
@@ -214,6 +212,41 @@ public class IFrameDeliveryMapper implements Mapper {
 		return mr;
 	}
 	
+	/**
+	 * @param path The path
+	 * @return A leaf
+	 */
+	private final VFSLeaf resolveFile(String path) {
+		VFSItem vfsItem = rootDir.resolve(path);
+		if(vfsItem == null && rootDir instanceof VFSContainer) {
+			path = VFSManager.sanitizePath(path);
+			List<VFSItem> items = null;
+			int lastSlash = path.lastIndexOf('/');
+			if(lastSlash == 0) {
+				String filename = path.substring(1);
+				items = ((VFSContainer)rootDir).getItems(new ByNameCaseInsensitive(filename));
+			} else if (lastSlash > 0) {
+				String containerPath = path.substring(0, lastSlash);
+				String filename = path.substring(lastSlash + 1);
+				VFSItem parentItem = rootDir.resolve(containerPath);
+				items = ((VFSContainer)parentItem).getItems(new ByNameCaseInsensitive(filename));
+			} else {
+				items = ((VFSContainer)rootDir).getItems(new ByNameCaseInsensitive(path));
+			}
+			
+			if(items != null && items.size() == 1) {
+				vfsItem = items.get(0);
+			}
+		}
+		
+		VFSLeaf vfsLeaf = null;
+		//only files are allowed, but somehow it happened that folders showed up here
+		if (vfsItem instanceof VFSLeaf) {
+			vfsLeaf = (VFSLeaf)vfsItem;
+		}
+		return vfsLeaf;
+	}
+	
 	private MediaResource deliverJavascriptFile(VFSLeaf vfsLeaf) {
 		VFSMediaResource vmr = new VFSMediaResource(vfsLeaf);
 		// set the encoding; could be null if this page starts with .js file
@@ -698,5 +731,18 @@ public class IFrameDeliveryMapper implements Mapper {
 			this.useLoadedPageString = useLoadedPageString;
 		}
 	}
+	
+	private static class ByNameCaseInsensitive implements VFSItemFilter {
+		
+		private final String filename;
+		
+		public ByNameCaseInsensitive(String filename) {
+			this.filename = filename;
+		}
 
+		@Override
+		public boolean accept(VFSItem vfsItem) {
+			return vfsItem != null && filename.equalsIgnoreCase(vfsItem.getName());
+		}
+	}
 }
diff --git a/src/main/java/org/olat/core/util/mail/ContactList.java b/src/main/java/org/olat/core/util/mail/ContactList.java
index a6d532605c229e4d95b8139ed8dfbc090027e568..3b8472984ad6616039577e30ab8062996d6ce1d4 100644
--- a/src/main/java/org/olat/core/util/mail/ContactList.java
+++ b/src/main/java/org/olat/core/util/mail/ContactList.java
@@ -154,7 +154,7 @@ public class ContactList {
 			rfc2047name = javax.mail.internet.MimeUtility.encodeWord(name, "UTF-8", null);
 		}
 		catch (java.io.UnsupportedEncodingException e) {
-			log.warn("Error MIME-encoding name: " + e, e);
+			log.warn("Error MIME-encoding name: ", e);
 			rfc2047name = name;
 		}
 
@@ -208,7 +208,7 @@ public class ContactList {
 		if (emailPrioInstitutional) {
 			for (Iterator<Identity> it=copy.iterator(); it.hasNext(); ) {
 				Identity tmp = it.next();
-				if(tmp.getStatus() == Identity.STATUS_LOGIN_DENIED) {
+				if(Identity.STATUS_LOGIN_DENIED.equals(tmp.getStatus())) {
 					continue;
 				}
 
@@ -223,7 +223,7 @@ public class ContactList {
 		 * loops over the (remaining) identities, fetches the user email.
 		 */
 		for (Identity tmp : copy){
-			if(tmp.getStatus() == Identity.STATUS_LOGIN_DENIED) {
+			if(Identity.STATUS_LOGIN_DENIED.equals(tmp.getStatus())) {
 				continue;
 			}
 			String email = tmp.getUser().getProperty(UserConstants.EMAIL, null);
@@ -304,16 +304,19 @@ public class ContactList {
 	}
 
 	private void setName(String nameP) {
-		if (!StringHelper.containsNoneOfCoDouSemi(nameP)){
-			log.warn("Contact list name \"" + nameP + "\" doesn't match "+ StringHelper.ALL_WITHOUT_COMMA_2POINT_STRPNT);
+		if (!StringHelper.containsNoneOfCoDouSemi(nameP)
+				|| nameP.contains("(") || nameP.contains(")")
+				|| nameP.contains("[") || nameP.contains("]")) {
+			log.warn("Contact list name \"{}\" doesn't match {}", nameP, StringHelper.ALL_WITHOUT_COMMA_2POINT_STRPNT);
 			//replace bad chars with bad char in rfc compliant comments
-			nameP = nameP.replaceAll(":","¦");
-			nameP = nameP.replaceAll(";","_");
-			nameP = nameP.replaceAll(",","-");
-			
-		}
-				
+			nameP = nameP.replace(":","¦")
+					.replace(";","_")
+					.replace(",","-")
+					.replace("(","_")
+					.replace(")","_")
+					.replace("[","_")
+					.replace("]","_");
+		}		
 		this.name = nameP;
 	}
-
 }
\ No newline at end of file
diff --git a/src/main/java/org/olat/core/util/mail/manager/MailManagerImpl.java b/src/main/java/org/olat/core/util/mail/manager/MailManagerImpl.java
index 4a8904710d69b25c0b33ad353cf1695d0a51d178..a6e69bccacd688db58583497c82209c920449340 100644
--- a/src/main/java/org/olat/core/util/mail/manager/MailManagerImpl.java
+++ b/src/main/java/org/olat/core/util/mail/manager/MailManagerImpl.java
@@ -30,6 +30,7 @@ import java.io.OutputStream;
 import java.io.StringReader;
 import java.io.StringWriter;
 import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -66,12 +67,10 @@ import javax.persistence.TypedQuery;
 
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
+import org.apache.logging.log4j.Logger;
 import org.apache.velocity.VelocityContext;
 import org.apache.velocity.app.VelocityEngine;
 import org.apache.velocity.context.Context;
-import org.apache.velocity.exception.MethodInvocationException;
-import org.apache.velocity.exception.ParseErrorException;
-import org.apache.velocity.exception.ResourceNotFoundException;
 import org.apache.velocity.runtime.RuntimeConstants;
 import org.olat.basesecurity.IdentityImpl;
 import org.olat.basesecurity.IdentityRef;
@@ -88,7 +87,6 @@ import org.olat.core.helpers.Settings;
 import org.olat.core.id.Identity;
 import org.olat.core.id.OLATResourceable;
 import org.olat.core.id.UserConstants;
-import org.apache.logging.log4j.Logger;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.Encoder;
 import org.olat.core.util.StringHelper;
@@ -189,8 +187,7 @@ public class MailManagerImpl implements MailManager, InitializingBean  {
 	public PublisherData getPublisherData() {
 		String data = "";
 		String businessPath = "[Inbox:0]";
-		PublisherData publisherData = new PublisherData("Inbox", data, businessPath);
-		return publisherData;
+		return new PublisherData("Inbox", data, businessPath);
 	}
 
 	@Override
@@ -285,8 +282,8 @@ public class MailManagerImpl implements MailManager, InitializingBean  {
 		
 		TypedQuery<DBMailAttachment> query = dbInstance.getCurrentEntityManager()
 				.createQuery(sb.toString(), DBMailAttachment.class)
-				.setParameter("checksum", new Long(checksum))
-				.setParameter("size", new Long(size))
+				.setParameter("checksum", Long.valueOf(checksum))
+				.setParameter("size", Long.valueOf(size))
 				.setParameter("name", name);
 		if(mimetype != null) {
 			query.setParameter("mimetype", mimetype);
@@ -402,7 +399,7 @@ public class MailManagerImpl implements MailManager, InitializingBean  {
 					marked = Boolean.FALSE;
 				}
 				if(!marked.equals(recipient.getMarked())) {
-					recipient.setMarked(marked.booleanValue());
+					recipient.setMarked(marked);
 					dbInstance.updateObject(recipient);
 					changed |= true;
 				}
@@ -603,7 +600,7 @@ public class MailManagerImpl implements MailManager, InitializingBean  {
 		File template = new File(baseFolder, "mail_template.html");
 		if(template.exists()) {
 			try(InputStream in = new FileInputStream(template)) {
-				return IOUtils.toString(in, "UTF-8");
+				return IOUtils.toString(in, StandardCharsets.UTF_8);
 			} catch (IOException e) {
 				log.error("", e);
 			}
@@ -621,7 +618,7 @@ public class MailManagerImpl implements MailManager, InitializingBean  {
 		File templateFile = new File(baseFolder, "mail_template.html");
 		try(OutputStream out = new FileOutputStream(templateFile);) {
 			StringReader reader = new StringReader(template);
-			IOUtils.copy(reader, out, "UTF-8");
+			IOUtils.copy(reader, out, StandardCharsets.UTF_8);
 		} catch (IOException e) {
 			log.error("", e);
 		}
@@ -643,7 +640,7 @@ public class MailManagerImpl implements MailManager, InitializingBean  {
 	@Override
 	public String getDefaultMailTemplate() {
 		try(InputStream in = MailModule.class.getResourceAsStream("_content/mail_template.html")) {
-			return IOUtils.toString(in, "UTF-8");
+			return IOUtils.toString(in, StandardCharsets.UTF_8);
 		} catch (IOException e) {
 			log.error("Cannot read the default mail template", e);
 			return null;
@@ -861,15 +858,6 @@ public class MailManagerImpl implements MailManager, InitializingBean  {
 				// template is empty
 				mailerResult.setReturnCode(MailerResult.OK);
 			}
-		} catch (ParseErrorException e) {
-			log.warn("can't send email from user template", e);
-			mailerResult.setReturnCode(MailerResult.TEMPLATE_PARSE_ERROR);
-		} catch (MethodInvocationException e) {
-			log.warn("can't send email from user template", e);
-			mailerResult.setReturnCode(MailerResult.TEMPLATE_GENERAL_ERROR);
-		} catch (ResourceNotFoundException e) {
-			log.warn("can't send email from user template", e);
-			mailerResult.setReturnCode(MailerResult.TEMPLATE_GENERAL_ERROR);
 		} catch (Exception e) {
 			log.warn("can't send email from user template", e);
 			mailerResult.setReturnCode(MailerResult.TEMPLATE_GENERAL_ERROR);
@@ -992,13 +980,13 @@ public class MailManagerImpl implements MailManager, InitializingBean  {
 			mail.setMetaId(metaId);
 			String subject = content.getSubject();
 			if(subject != null && subject.length() > 500) {
-				log.warn("Cut a too long subkect in name. Size: " + subject.length());
+				log.warn("Cut a too long subkect in name. Size: {}", subject.length());
 				subject = subject.substring(0, 500);
 			}
 			mail.setSubject(subject);
 			String body = content.getBody();
 			if(body != null && body.length() > 16777210) {
-				log.warn("Cut a too long body in mail. Size: " + body.length());
+				log.warn("Cut a too long body in mail. Size: {}", body.length());
 				body = body.substring(0, 16000000);
 			}
 			mail.setBody(body);
@@ -1009,7 +997,7 @@ public class MailManagerImpl implements MailManager, InitializingBean  {
 				if(ores != null) {
 					String resName = ores.getResourceableTypeName();
 					if(resName != null && resName.length() > 50) {
-						log.warn("Cut a too long resourceable type name in mail context: " + resName);
+						log.warn("Cut a too long resourceable type name in mail context: {}", resName);
 						resName = resName.substring(0, 49);
 					}
 					mail.getContext().setResName(ores.getResourceableTypeName());
@@ -1018,14 +1006,14 @@ public class MailManagerImpl implements MailManager, InitializingBean  {
 				
 				String resSubPath = context.getResSubPath();
 				if(resSubPath != null && resSubPath.length() > 2000) {
-					log.warn("Cut a too long resSubPath in mail context: " + resSubPath);
+					log.warn("Cut a too long resSubPath in mail context: {}", resSubPath);
 					resSubPath = resSubPath.substring(0, 2000);
 				}
 				mail.getContext().setResSubPath(resSubPath);
 				
 				String businessPath = context.getBusinessPath();
 				if(businessPath != null && businessPath.length() > 2000) {
-					log.warn("Cut a too long resSubPath in mail context: " + businessPath);
+					log.warn("Cut a too long resSubPath in mail context: {}", businessPath);
 					businessPath = businessPath.substring(0, 2000);
 				}
 				mail.getContext().setBusinessPath(businessPath);
@@ -1383,8 +1371,7 @@ public class MailManagerImpl implements MailManager, InitializingBean  {
 		}
 		
 		try {
-			Address add = new InternetAddress(address);
-			return add;
+			return new InternetAddress(address);
 		} catch (AddressException e) {
 			result.setReturnCode(MailerResult.SENDER_ADDRESS_ERROR);
 			throw e;
@@ -1556,8 +1543,7 @@ public class MailManagerImpl implements MailManager, InitializingBean  {
 					// abort if attachment does not exist
 					if (attachment == null || attachment.getSize()  <= 0) {
 						result.setReturnCode(MailerResult.ATTACHMENT_INVALID);
-						log.error("Tried to send mail wit attachment that does not exist::"
-								+ (attachment == null ? null : attachment.getName()));
+						log.error("Tried to send mail wit attachment that does not exist:: {}", (attachment == null ? null : attachment.getName()));
 						return msg;
 					}
 					BodyPart messageBodyPart = new MimeBodyPart();
@@ -1737,8 +1723,7 @@ public class MailManagerImpl implements MailManager, InitializingBean  {
 					// abort if attachment does not exist
 					if (attachmentFile == null || !attachmentFile.exists()) {
 						result.setReturnCode(MailerResult.ATTACHMENT_INVALID);
-						log.error("Tried to send mail wit attachment that does not exist::"
-								+ (attachmentFile == null ? null : attachmentFile.getAbsolutePath()));
+						log.error("Tried to send mail wit attachment that does not exist::{}", (attachmentFile == null ? null : attachmentFile.getAbsolutePath()));
 						return msg;
 					}
 					BodyPart filePart = new MimeBodyPart();
diff --git a/src/main/java/org/olat/modules/lecture/LectureService.java b/src/main/java/org/olat/modules/lecture/LectureService.java
index 249e79a6102347752b046b335bc39f2609f2e04b..19e6ba480e63832917a3fb2380bdd38b19ca17e1 100644
--- a/src/main/java/org/olat/modules/lecture/LectureService.java
+++ b/src/main/java/org/olat/modules/lecture/LectureService.java
@@ -220,7 +220,7 @@ public interface LectureService {
 	 * 
 	 * @param block The block to delete.
 	 */
-	public void deleteLectureBlock(LectureBlock block);
+	public void deleteLectureBlock(LectureBlock block, Identity doer);
 	
 	/**
 	 * Delete all the lecture blocks and configuration of the specified course.
@@ -346,6 +346,8 @@ public interface LectureService {
 
 	public List<AbsenceNoticeInfos> searchAbsenceNotices(AbsenceNoticeSearchParameters searchParams);
 	
+	public List<AbsenceNotice> getAbsenceNoticeUniquelyRelatedTo(List<LectureBlock> blocks);
+	
 	/**
 	 * Detect an absence notice for the specified identity.
 	 * 
diff --git a/src/main/java/org/olat/modules/lecture/manager/AbsenceNoticeToLectureBlockDAO.java b/src/main/java/org/olat/modules/lecture/manager/AbsenceNoticeToLectureBlockDAO.java
index ef8a58fa2736a233878c36976ddb2c52a551d3f1..d58b7019e37ed4ae963b0e8b7a19db1dda99b47e 100644
--- a/src/main/java/org/olat/modules/lecture/manager/AbsenceNoticeToLectureBlockDAO.java
+++ b/src/main/java/org/olat/modules/lecture/manager/AbsenceNoticeToLectureBlockDAO.java
@@ -19,8 +19,11 @@
  */
 package org.olat.modules.lecture.manager;
 
+import java.util.ArrayList;
 import java.util.Date;
+import java.util.HashSet;
 import java.util.List;
+import java.util.stream.Collectors;
 
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.commons.persistence.QueryBuilder;
@@ -80,6 +83,42 @@ public class AbsenceNoticeToLectureBlockDAO {
 				.getResultList();
 	}
 	
+	/**
+	 * Return all relations of notices which has a relation with
+	 * the specified lecture blocks.
+	 * 
+	 * @param blocks A list of lecture blocks
+	 * @return A list of absence notice to lecture block relationship
+	 */
+	public List<AbsenceNoticeToLectureBlock> getRelationsAStepFurther(List<LectureBlock> blocks) {
+		if(blocks == null || blocks.isEmpty()) return new ArrayList<>();
+		
+		QueryBuilder sb = new QueryBuilder(255);
+		sb.append("select targetNoticeToBlock from absencenoticetolectureblock noticeToBlock")
+		  .append(" inner join noticeToBlock.absenceNotice as notice")
+		  .append(" inner join absencenoticetolectureblock as targetNoticeToBlock on (targetNoticeToBlock.absenceNotice.key=notice.key)")
+		  .append(" inner join fetch targetNoticeToBlock.absenceNotice as targetNotice")
+		  .append(" inner join fetch targetNoticeToBlock.lectureBlock as targetLectureBlock")
+		  .append(" where noticeToBlock.lectureBlock.key in (:lectureBlockKeys)");
+		
+		List<Long> lectureBlockKeys = blocks.stream()
+				.map(LectureBlock::getKey)
+				.collect(Collectors.toList());
+		List<AbsenceNoticeToLectureBlock> relations= dbInstance.getCurrentEntityManager()
+				.createQuery(sb.toString(), AbsenceNoticeToLectureBlock.class)
+				.setParameter("lectureBlockKeys", lectureBlockKeys)
+				.getResultList();
+		return new ArrayList<>(new HashSet<>(relations));
+	}
+	
+	public int deleteRelations(LectureBlock lectureBlock) {
+		String query = "delete from absencenoticetolectureblock noticeToBlock where noticeToBlock.lectureBlock.key=:lectureBlockKey";
+		return dbInstance.getCurrentEntityManager()
+				.createQuery(query)
+				.setParameter("lectureBlockKey", lectureBlock.getKey())
+				.executeUpdate();
+	}
+	
 	public void deleteRelations(List<AbsenceNoticeToLectureBlock> relations) {
 		for(AbsenceNoticeToLectureBlock relation:relations) {
 			deleteRelation(relation);
diff --git a/src/main/java/org/olat/modules/lecture/manager/LectureServiceImpl.java b/src/main/java/org/olat/modules/lecture/manager/LectureServiceImpl.java
index 193d4f228ac7af4a89dca6486bd7b35b7504e0e3..761ae338f64c38e9366e2a796ab85ca599c1a3d1 100644
--- a/src/main/java/org/olat/modules/lecture/manager/LectureServiceImpl.java
+++ b/src/main/java/org/olat/modules/lecture/manager/LectureServiceImpl.java
@@ -33,6 +33,7 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
 
 import org.apache.logging.log4j.Logger;
@@ -430,7 +431,7 @@ public class LectureServiceImpl implements LectureService, UserDataDeletable, De
 	}
 
 	@Override
-	public void deleteLectureBlock(LectureBlock lectureBlock) {
+	public void deleteLectureBlock(LectureBlock lectureBlock, Identity actingIdentity) {
 		//first remove events
 		LectureBlock reloadedBlock = lectureBlockDao.loadByKey(lectureBlock.getKey());
 		RepositoryEntry entry = reloadedBlock.getEntry();
@@ -442,7 +443,44 @@ public class LectureServiceImpl implements LectureService, UserDataDeletable, De
 			List<Identity> teachers = getTeachers(reloadedBlock);
 			unsyncInternalCalendar(reloadedBlock, teachers);
 		}
+		
+		List<AbsenceNotice> absenceNotices = getAbsenceNoticeUniquelyRelatedTo(Collections.singletonList(lectureBlock));
+		for(AbsenceNotice absenceNotice:absenceNotices) {
+			deleteAbsenceNotice(absenceNotice, actingIdentity);
+		}
+		absenceNoticeToLectureBlockDao.deleteRelations(reloadedBlock);
 		lectureBlockDao.delete(reloadedBlock);
+		dbInstance.commit();// make it quick
+	}
+
+	@Override
+	public List<AbsenceNotice> getAbsenceNoticeUniquelyRelatedTo(List<LectureBlock> blocks) {
+		List<AbsenceNoticeToLectureBlock> relations = absenceNoticeToLectureBlockDao.getRelationsAStepFurther(blocks);
+
+		Set<Long> lectureBlockKeys = blocks.stream()
+				.map(LectureBlock::getKey)
+				.collect(Collectors.toSet());
+		
+		Map<AbsenceNotice,AtomicInteger> counters = new HashMap<>();
+		for(AbsenceNoticeToLectureBlock relation:relations) {
+			AbsenceNotice notice = relation.getAbsenceNotice();
+			LectureBlock lectureBlock = relation.getLectureBlock();
+			
+			AtomicInteger counter = counters
+					.computeIfAbsent(notice, n -> new AtomicInteger(0));
+			if(!lectureBlockKeys.contains(lectureBlock.getKey())) {
+				counter.incrementAndGet();
+			}
+		}
+		
+		List<AbsenceNotice> uniquelyRelated = new ArrayList<>();
+		for(Map.Entry<AbsenceNotice,AtomicInteger> counterEntry:counters.entrySet()) {
+			int count = counterEntry.getValue().intValue();
+			if(count == 0) {
+				uniquelyRelated.add(counterEntry.getKey());
+			}
+		}
+		return uniquelyRelated;
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/modules/lecture/restapi/LectureBlockWebService.java b/src/main/java/org/olat/modules/lecture/restapi/LectureBlockWebService.java
index 4cdb6c6cc43fa941b5956948ca4af75031ad2693..bb45fd9c3bd45e4348c8594b0302730b7101f98e 100644
--- a/src/main/java/org/olat/modules/lecture/restapi/LectureBlockWebService.java
+++ b/src/main/java/org/olat/modules/lecture/restapi/LectureBlockWebService.java
@@ -153,8 +153,8 @@ public class LectureBlockWebService {
 			@ApiResponse(responseCode = "404", description = "Not found.") })
 	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
 	public Response deleteLectureBlock() {
-		lectureService.deleteLectureBlock(lectureBlock);
-		log.info(Tracing.M_AUDIT, "Lecture block deleted: " + lectureBlock);
+		lectureService.deleteLectureBlock(lectureBlock, null);
+		log.info(Tracing.M_AUDIT, "Lecture block deleted: {}", lectureBlock);
 		return Response.ok().build();
 	}
 
diff --git a/src/main/java/org/olat/modules/lecture/ui/ConfirmDeleteLectureBlockController.java b/src/main/java/org/olat/modules/lecture/ui/ConfirmDeleteLectureBlockController.java
new file mode 100644
index 0000000000000000000000000000000000000000..540fadc7fdb74c24c32b6a3868da6814cfe67573
--- /dev/null
+++ b/src/main/java/org/olat/modules/lecture/ui/ConfirmDeleteLectureBlockController.java
@@ -0,0 +1,171 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.modules.lecture.ui;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.form.flexible.FormItem;
+import org.olat.core.gui.components.form.flexible.FormItemContainer;
+import org.olat.core.gui.components.form.flexible.elements.FormLink;
+import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement;
+import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
+import org.olat.core.gui.components.form.flexible.impl.FormEvent;
+import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
+import org.olat.core.gui.components.link.Link;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.Event;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.id.Identity;
+import org.olat.core.logging.activity.CoreLoggingResourceable;
+import org.olat.core.logging.activity.LearningResourceLoggingAction;
+import org.olat.core.logging.activity.OlatResourceableType;
+import org.olat.core.logging.activity.ThreadLocalUserActivityLogger;
+import org.olat.core.util.StringHelper;
+import org.olat.modules.lecture.AbsenceNotice;
+import org.olat.modules.lecture.LectureBlock;
+import org.olat.modules.lecture.LectureBlockManagedFlag;
+import org.olat.modules.lecture.LectureService;
+import org.olat.user.UserManager;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * 
+ * Initial date: 5 déc. 2019<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class ConfirmDeleteLectureBlockController extends FormBasicController {
+	
+	private static final String[] confirmKeys = new String[] { "confirm" };
+	
+	private FormLink deleteButton;
+	private MultipleSelectionElement confirmEl;
+	
+	private final List<LectureBlock> blocks;
+	
+	@Autowired
+	private UserManager userManager;
+	@Autowired
+	private LectureService lectureService;
+	
+	public ConfirmDeleteLectureBlockController(UserRequest ureq, WindowControl wControl, List<LectureBlock> blocks) {
+		super(ureq, wControl, "confirm_delete");
+		this.blocks = blocks;
+		initForm(ureq);
+	}
+	
+	public List<LectureBlock> getBlocks() {
+		return blocks;
+	}
+
+	@Override
+	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		if(formLayout instanceof FormLayoutContainer) {
+			StringBuilder titles = new StringBuilder(128);
+			for(LectureBlock block:blocks) {
+				if(titles.length() > 0) titles.append(", ");
+				titles.append(StringHelper.escapeHtml(block.getTitle()));
+			}
+			String text = translate("confirm.delete.lectures", new String[] { titles.toString() });
+			((FormLayoutContainer)formLayout).contextPut("msg", text);
+		}
+		
+		List<AbsenceNotice> notices = lectureService.getAbsenceNoticeUniquelyRelatedTo(blocks);
+		if(!notices.isEmpty()) {
+			// confirmation delete notices
+			Set<Identity> identities = new HashSet<>();
+			for(AbsenceNotice notice:notices) {
+				identities.add(notice.getIdentity());
+			}
+
+			StringBuilder names = new StringBuilder(128);
+			for(Identity identity:identities) {
+				String name = userManager.getUserDisplayName(identity);
+				if(names.length() > 0) names.append(", ");
+				names.append(name);
+			}
+
+			String text = translate("confirm.delete.lectures.notices", new String[] { Integer.toString(notices.size()),  names.toString() });
+			((FormLayoutContainer)formLayout).contextPut("noticeMsg", text);
+
+			String[] confirmationValues = new String[] {translate("confirm.delete.lectures.notices.confirmation") };
+			confirmEl = uifactory.addCheckboxesHorizontal("confirm", "confirm.delete.lectures.notices.confirmation", formLayout, confirmKeys, confirmationValues);
+		}
+		deleteButton = uifactory.addFormLink("delete", formLayout, Link.BUTTON);
+		uifactory.addFormCancelButton("cancel", formLayout, ureq, getWindowControl());
+	}
+
+	@Override
+	protected void doDispose() {
+		//
+	}
+	
+	@Override
+	protected boolean validateFormLogic(UserRequest ureq) {
+		boolean allOk = super.validateFormLogic(ureq);
+		
+		if(confirmEl != null) {
+			confirmEl.clearError();
+			if(!confirmEl.isAtLeastSelected(1)) {
+				confirmEl.setErrorKey("form.legende.mandatory", null);
+				allOk &= false;
+			}
+		}
+		
+		return allOk;
+	}
+
+	@Override
+	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
+		if(deleteButton == source) {
+			if(validateFormLogic(ureq)) {
+				doDeleteLectureBlocks(ureq);
+			}
+		}
+		super.formInnerEvent(ureq, source, event);
+	}
+
+	@Override
+	protected void formCancelled(UserRequest ureq) {
+		fireEvent(ureq, Event.CANCELLED_EVENT);
+	}
+
+	@Override
+	protected void formOK(UserRequest ureq) {
+		//
+	}
+	
+	private void doDeleteLectureBlocks(UserRequest ureq) {
+		for(LectureBlock block:blocks) {
+			if(LectureBlockManagedFlag.isManaged(block, LectureBlockManagedFlag.delete)) {
+				continue;
+			}
+			lectureService.deleteLectureBlock(block, getIdentity());
+			logAudit("Lecture block deleted: " + block);
+			ThreadLocalUserActivityLogger.log(LearningResourceLoggingAction.LECTURE_BLOCK_DELETED, getClass(),
+					CoreLoggingResourceable.wrap(block, OlatResourceableType.lectureBlock, block.getTitle()));
+		}
+		showInfo("lecture.deleted");
+		fireEvent(ureq, Event.DONE_EVENT);
+	}
+}
diff --git a/src/main/java/org/olat/modules/lecture/ui/LectureListRepositoryController.java b/src/main/java/org/olat/modules/lecture/ui/LectureListRepositoryController.java
index 27707d77684ef56bec2f7f20437e6ed84beca8ab..a3b9dacbb5bdb7791915e815225a09ba5fb01873 100644
--- a/src/main/java/org/olat/modules/lecture/ui/LectureListRepositoryController.java
+++ b/src/main/java/org/olat/modules/lecture/ui/LectureListRepositoryController.java
@@ -53,8 +53,6 @@ import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.controller.BasicController;
 import org.olat.core.gui.control.generic.closablewrapper.CloseableCalloutWindowController;
 import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
-import org.olat.core.gui.control.generic.modal.DialogBoxController;
-import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory;
 import org.olat.core.gui.control.generic.wizard.Step;
 import org.olat.core.gui.control.generic.wizard.StepRunnerCallback;
 import org.olat.core.gui.control.generic.wizard.StepsMainRunController;
@@ -63,7 +61,6 @@ import org.olat.core.logging.activity.CoreLoggingResourceable;
 import org.olat.core.logging.activity.LearningResourceLoggingAction;
 import org.olat.core.logging.activity.OlatResourceableType;
 import org.olat.core.logging.activity.ThreadLocalUserActivityLogger;
-import org.olat.core.util.StringHelper;
 import org.olat.modules.lecture.LectureBlock;
 import org.olat.modules.lecture.LectureBlockAuditLog;
 import org.olat.modules.lecture.LectureBlockManagedFlag;
@@ -101,11 +98,10 @@ public class LectureListRepositoryController extends FormBasicController {
 	
 	private ToolsController toolsCtrl;
 	private CloseableModalController cmc;
-	private DialogBoxController deleteDialogCtrl;
 	private StepsMainRunController importBlockWizard;
-	private DialogBoxController bulkDeleteDialogCtrl;
 	private EditLectureBlockController editLectureCtrl;
 	private CloseableCalloutWindowController toolsCalloutCtrl;
+	private ConfirmDeleteLectureBlockController deleteLectureBlocksCtrl;
 
 	private int counter = 0;
 	private final RepositoryEntry entry;
@@ -269,34 +265,23 @@ public class LectureListRepositoryController extends FormBasicController {
 			if(event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) {
 				loadModel();
 			}
-		} else if(deleteDialogCtrl == source) {
-			if (DialogBoxUIFactory.isYesEvent(event) || DialogBoxUIFactory.isOkEvent(event)) {
-				LectureBlockRow row = (LectureBlockRow)deleteDialogCtrl.getUserObject();
-				doDelete(row);
+		} else if(deleteLectureBlocksCtrl == source) {
+			if (event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) {
 				loadModel();
-				cleanUp();
-			}
-		} else if(bulkDeleteDialogCtrl == source) {
-			if (DialogBoxUIFactory.isYesEvent(event) || DialogBoxUIFactory.isOkEvent(event)) {
-				@SuppressWarnings("unchecked")
-				List<LectureBlock> blocks = (List<LectureBlock>)bulkDeleteDialogCtrl.getUserObject();
-				doDelete(blocks);
-				loadModel();
-				cleanUp();
 			}
+			cmc.deactivate();
+			cleanUp();
 		}
 		super.event(ureq, source, event);
 	}
 	
 	private void cleanUp() {
-		removeAsListenerAndDispose(bulkDeleteDialogCtrl);
-		removeAsListenerAndDispose(deleteDialogCtrl);
+		removeAsListenerAndDispose(deleteLectureBlocksCtrl);
 		removeAsListenerAndDispose(editLectureCtrl);
 		removeAsListenerAndDispose(toolsCalloutCtrl);
 		removeAsListenerAndDispose(toolsCtrl);
 		removeAsListenerAndDispose(cmc);
-		bulkDeleteDialogCtrl = null;
-		deleteDialogCtrl = null;
+		deleteLectureBlocksCtrl = null;
 		toolsCalloutCtrl = null;
 		editLectureCtrl = null;
 		toolsCtrl = null;
@@ -391,45 +376,27 @@ public class LectureListRepositoryController extends FormBasicController {
 		if(blocks.isEmpty()) {
 			showWarning("error.atleastone.lecture");
 		} else {
-			StringBuilder titles = new StringBuilder();
-			for(LectureBlock block:blocks) {
-				if(titles.length() > 0) titles.append(", ");
-				titles.append(StringHelper.escapeHtml(block.getTitle()));
-			}
-			String text = translate("confirm.delete.lectures", new String[] { titles.toString() });
-			bulkDeleteDialogCtrl = activateYesNoDialog(ureq, translate("delete.lectures.title"), text, bulkDeleteDialogCtrl);
-			bulkDeleteDialogCtrl.setUserObject(blocks);
+			deleteLectureBlocksCtrl = new ConfirmDeleteLectureBlockController(ureq, getWindowControl(), blocks);
+			listenTo(deleteLectureBlocksCtrl);
+			
+			String title = translate("delete.lectures.title");
+			cmc = new CloseableModalController(getWindowControl(), "close", deleteLectureBlocksCtrl.getInitialComponent(), true, title);
+			listenTo(cmc);
+			cmc.activate();
 		}
 	}
 	
 	private void doConfirmDelete(UserRequest ureq, LectureBlockRow row) {
-		String text = translate("confirm.delete.lectures", new String[] { row.getLectureBlock().getTitle() });
-		deleteDialogCtrl = activateYesNoDialog(ureq, translate("delete.lectures.title"), text, deleteDialogCtrl);
-		deleteDialogCtrl.setUserObject(row);
-	}
-	
-	private void doDelete(LectureBlockRow row) {
-		if(LectureBlockManagedFlag.isManaged(row.getLectureBlock(), LectureBlockManagedFlag.delete)) return;
+		List<LectureBlock> blocks = Collections.singletonList(row.getLectureBlock());
+		deleteLectureBlocksCtrl = new ConfirmDeleteLectureBlockController(ureq, getWindowControl(), blocks);
+		listenTo(deleteLectureBlocksCtrl);
 		
-		LectureBlock lectureBlock = row.getLectureBlock();
-		lectureService.deleteLectureBlock(lectureBlock);
-		showInfo("lecture.deleted");
-		logAudit("Lecture block deleted: " + lectureBlock);
-		ThreadLocalUserActivityLogger.log(LearningResourceLoggingAction.LECTURE_BLOCK_DELETED, getClass(),
-				CoreLoggingResourceable.wrap(lectureBlock, OlatResourceableType.lectureBlock, lectureBlock.getTitle()));
-		
-	}
-	
-	private void doDelete(List<LectureBlock> blocks) {
-		for(LectureBlock block:blocks) {
-			lectureService.deleteLectureBlock(block);
-			logAudit("Lecture block deleted: " + block);
-			ThreadLocalUserActivityLogger.log(LearningResourceLoggingAction.LECTURE_BLOCK_DELETED, getClass(),
-					CoreLoggingResourceable.wrap(block, OlatResourceableType.lectureBlock, block.getTitle()));
-		}
-		showInfo("lecture.deleted");
+		String title = translate("delete.lectures.title");
+		cmc = new CloseableModalController(getWindowControl(), "close", deleteLectureBlocksCtrl.getInitialComponent(), true, title);
+		listenTo(cmc);
+		cmc.activate();
 	}
-	
+
 	private void doExportLog(UserRequest ureq, LectureBlockRow row) {
 		LectureBlock lectureBlock = lectureService.getLectureBlock(row);
 		List<LectureBlockAuditLog> auditLog = lectureService.getAuditLog(row);
diff --git a/src/main/java/org/olat/modules/lecture/ui/_content/confirm_delete.html b/src/main/java/org/olat/modules/lecture/ui/_content/confirm_delete.html
new file mode 100644
index 0000000000000000000000000000000000000000..82a35bdac8c4dc78e98ea2920be5473ea11dea9b
--- /dev/null
+++ b/src/main/java/org/olat/modules/lecture/ui/_content/confirm_delete.html
@@ -0,0 +1,15 @@
+<div class="o_warning" role="alert">$msg
+#if($r.isNotEmpty($noticeMsg))
+	<br><i class="o_icon o_icon-lg o_icon_important"> </i> $noticeMsg
+#end
+</div>
+#if($r.available("confirm"))
+	$r.render("confirm")
+	#if($f.hasError("confirm"))
+		$r.render("confirm_ERROR")
+	#end
+#end
+<div class="o_button_group">
+	$r.render("cancel")
+	$r.render("delete")
+</div>
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_de.properties
index bbbb3ff301f3fdec7453b5883b9107a5280b1b57..3df1c8ce7e0d7f04643f692052d06c4a3dfe7147 100644
--- a/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_de.properties
@@ -99,6 +99,8 @@ confirm.delete.dispensation=Wollen Sie die Dispens von "{0}" l\u00F6schen? Die P
 confirm.delete.assessment.mode.text=Wollen Sie wirklich diesen Pr\u00FCfungsmodus von Lektionenblock "{0}" l\u00F6schen?
 confirm.delete.assessment.mode.title=Pr\u00FCfungsmodus l\u00F6schen
 confirm.delete.lectures=Wollen Sie wirklich diesen Lektionenblock "{0}" l\u00F6schen?
+confirm.delete.lectures.notices=<strong>{0}</strong> Absenze(n) / Abmeldunge(n) f\u00FCr "<strong>{1}</strong>" die nur zu den Lektionbl\u00F6cke geh\u00F6ren werden mit gel\u00F6scht. 
+confirm.delete.lectures.notices.confirmation=Ich verstehe dass die Absenzen / Abmeldungen definitv gel\u00F6scht werden.
 confirm.delete.reason=Wollen Sie wirklich diese Begr\u00FCndung "{0}" l\u00F6schen?
 contact.teachers=Dozenten kontaktieren
 contact.teachers.list.name=Dozenten
diff --git a/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_en.properties
index 9dfdfaf9cfcc52e13294f3cc0a46de32712335eb..17e573a88ea36bfd640278510c34fb33a3fc69ca 100644
--- a/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_en.properties
@@ -99,6 +99,8 @@ confirm.delete.assessment.mode.text=Do you really want to delete the exam of thi
 confirm.delete.assessment.mode.title=Delete exam
 confirm.delete.dispensation=Do you really want to delete the dispensation of "{0}"? The person will be considered present.
 confirm.delete.lectures=Do you really want to delete these lectures "{0}"?
+confirm.delete.lectures.notices=<strong>{0}</strong> absences / dispensation for "<strong>{1}</strong>" which only linked to the lecture blocks will be deleted. 
+confirm.delete.lectures.notices.confirmation=I understand that the absences / dispensation will be definitively deleted.
 confirm.delete.reason=Do you really want to delete this reason "{0}"?
 contact.teachers=Contact teachers
 contact.teachers.list.name=Teachers
diff --git a/src/test/java/org/olat/modules/lecture/manager/AbsenceNoticeToLectureBlockDAOTest.java b/src/test/java/org/olat/modules/lecture/manager/AbsenceNoticeToLectureBlockDAOTest.java
index ca518b79c841011b4b1fbf36b88e0eefc0ab4cb4..f1215ec75b5030ebf9980afacd275aeeecc8f290 100644
--- a/src/test/java/org/olat/modules/lecture/manager/AbsenceNoticeToLectureBlockDAOTest.java
+++ b/src/test/java/org/olat/modules/lecture/manager/AbsenceNoticeToLectureBlockDAOTest.java
@@ -19,6 +19,7 @@
  */
 package org.olat.modules.lecture.manager;
 
+import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Collections;
 import java.util.Date;
@@ -194,6 +195,35 @@ public class AbsenceNoticeToLectureBlockDAOTest extends OlatTestCase {
 		Assert.assertFalse(rollCallList.contains(oldRollCall1));
 	}
 	
+	@Test
+	public void getRelationsAStepFurther() {
+		
+		RepositoryEntry entry = JunitTestHelper.createAndPersistRepositoryEntry();
+		LectureBlock lectureBlockEntry1 = createMinimalLectureBlock(entry, new Date(), new Date());
+		LectureBlock lectureBlockEntry2 = createMinimalLectureBlock(entry, new Date(), new Date());
+		List<LectureBlock> lectureBlockEntries = new ArrayList<>();
+		lectureBlockEntries.add(lectureBlockEntry1);
+		lectureBlockEntries.add(lectureBlockEntry2);
+
+		Identity participant = JunitTestHelper.createAndPersistIdentityAsRndUser("absent-1");
+		AbsenceNotice notice = lectureService.createAbsenceNotice(participant, AbsenceNoticeType.absence, AbsenceNoticeTarget.entries,
+				CalendarUtils.startOfDay(new Date()), CalendarUtils.endOfDay(new Date()),
+				null, null, Boolean.TRUE, null, lectureBlockEntries, null);
+		dbInstance.commitAndCloseSession();
+		
+		List<AbsenceNoticeToLectureBlock> relations = absenceNoticeToLectureBlockDao
+				.getRelationsAStepFurther(Collections.singletonList(lectureBlockEntry1));
+		dbInstance.commitAndCloseSession();
+		
+		Assert.assertNotNull(relations);
+		Assert.assertEquals(2, relations.size());
+		
+		for(AbsenceNoticeToLectureBlock relation:relations) {
+			Assert.assertEquals(notice, relation.getAbsenceNotice());
+			Assert.assertTrue(lectureBlockEntries.remove(relation.getLectureBlock()));
+		}
+	}
+	
 	private LectureBlock createMinimalLectureBlock(RepositoryEntry entry, Date start, Date end) {
 		LectureBlock lectureBlock = lectureBlockDao.createLectureBlock(entry);
 		lectureBlock.setStartDate(start);
diff --git a/src/test/java/org/olat/modules/lecture/manager/LectureServiceTest.java b/src/test/java/org/olat/modules/lecture/manager/LectureServiceTest.java
index b1cecbe2a5a53ed8fd96aeaacae1f5a09a577421..38093ba9a396d0d39918364678cecb91f8298441 100644
--- a/src/test/java/org/olat/modules/lecture/manager/LectureServiceTest.java
+++ b/src/test/java/org/olat/modules/lecture/manager/LectureServiceTest.java
@@ -501,6 +501,218 @@ public class LectureServiceTest extends OlatTestCase {
 		Assert.assertNull(reloadedRollCall3.getAbsenceNotice());
 	}
 	
+	@Test
+	public void getAbsenceNoticeUniquelyRelatedTo() {
+		Identity participant1 = JunitTestHelper.createAndPersistIdentityAsRndUser("noticee-1");
+		Identity participant2 = JunitTestHelper.createAndPersistIdentityAsRndUser("noticee-2");
+		RepositoryEntry entry1 = JunitTestHelper.createAndPersistRepositoryEntry();
+		RepositoryEntry entry2 = JunitTestHelper.createAndPersistRepositoryEntry();
+
+		LectureBlock block1 = createMinimalLectureBlock(entry1);
+		LectureBlock block2 = createMinimalLectureBlock(entry2);
+		LectureBlock block3 = createMinimalLectureBlock(entry2);
+		LectureBlock block4 = createMinimalLectureBlock(entry2);
+		dbInstance.commit();
+
+		List<LectureBlock> lectureBlocks = new ArrayList<>();
+		lectureBlocks.add(block1);
+		lectureBlocks.add(block2);
+
+		AbsenceNotice notice1_2 = lectureService.createAbsenceNotice(participant1, AbsenceNoticeType.notified, AbsenceNoticeTarget.lectureblocks,
+				new Date(), new Date(), null, null, null, null, lectureBlocks, null);
+		AbsenceNotice notice1_2_alt = lectureService.createAbsenceNotice(participant2, AbsenceNoticeType.notified, AbsenceNoticeTarget.lectureblocks,
+				new Date(), new Date(), null, null, null, null, lectureBlocks, null);
+		AbsenceNotice notice3 = lectureService.createAbsenceNotice(participant1, AbsenceNoticeType.notified, AbsenceNoticeTarget.lectureblocks,
+				new Date(), new Date(), null, null, null, null, Collections.singletonList(block3), null);
+		AbsenceNotice notice3b = lectureService.createAbsenceNotice(participant2, AbsenceNoticeType.notified, AbsenceNoticeTarget.lectureblocks,
+				new Date(), new Date(), null, null, null, null, Collections.singletonList(block3), null);
+		
+		List<LectureBlock> lectureSecondBlocks = new ArrayList<>();
+		lectureSecondBlocks.add(block1);
+		lectureSecondBlocks.add(block2);
+		lectureSecondBlocks.add(block4);
+		
+		AbsenceNotice notice4 = lectureService.createAbsenceNotice(participant2, AbsenceNoticeType.notified, AbsenceNoticeTarget.lectureblocks,
+				new Date(), new Date(), null, null, null, null, lectureSecondBlocks, null);
+		dbInstance.commit();
+		Assert.assertNotNull(notice4);
+		Assert.assertNotNull(notice1_2);
+		Assert.assertNotNull(notice1_2_alt);
+		
+		List<LectureBlock> allLectureBlocks = new ArrayList<>();
+		allLectureBlocks.add(block1);
+		allLectureBlocks.add(block3);
+		
+		// check block 1 + 3
+		List<AbsenceNotice> uniquelyRelatedNotices = lectureService.getAbsenceNoticeUniquelyRelatedTo(allLectureBlocks);
+		Assert.assertNotNull(uniquelyRelatedNotices);
+		Assert.assertEquals(2, uniquelyRelatedNotices.size());
+		Assert.assertTrue(uniquelyRelatedNotices.contains(notice3));
+		Assert.assertTrue(uniquelyRelatedNotices.contains(notice3b));
+
+		List<AbsenceNotice> uniquelyRelatedNoticesTo4 = lectureService.getAbsenceNoticeUniquelyRelatedTo(Collections.singletonList(block4));
+		Assert.assertNotNull(uniquelyRelatedNoticesTo4);
+		Assert.assertTrue(uniquelyRelatedNoticesTo4.isEmpty());
+		
+		// dummy check
+		List<AbsenceNotice> emptyList = lectureService.getAbsenceNoticeUniquelyRelatedTo(Collections.emptyList());
+		Assert.assertNotNull(emptyList);
+		Assert.assertTrue(emptyList.isEmpty());
+	}
+	
+	@Test
+	public void getAbsenceNoticeUniquelyRelatedTo_minimal() {
+		Identity participant = JunitTestHelper.createAndPersistIdentityAsRndUser("noticee-3");
+		RepositoryEntry entry = JunitTestHelper.createAndPersistRepositoryEntry();
+
+		LectureBlock block = createMinimalLectureBlock(entry);
+		dbInstance.commit();
+
+		AbsenceNotice noticeEntries = lectureService.createAbsenceNotice(participant, AbsenceNoticeType.notified, AbsenceNoticeTarget.allentries,
+				new Date(), new Date(), null, null, null, null, null, null);
+		AbsenceNotice noticeLectures = lectureService.createAbsenceNotice(participant, AbsenceNoticeType.notified, AbsenceNoticeTarget.lectureblocks,
+				new Date(), new Date(), null, null, null, null, Collections.singletonList(block), null);
+
+		// check
+		List<AbsenceNotice> uniquelyRelatedNotices = lectureService.getAbsenceNoticeUniquelyRelatedTo(Collections.singletonList(block));
+		Assert.assertNotNull(uniquelyRelatedNotices);
+		Assert.assertEquals(1, uniquelyRelatedNotices.size());
+		Assert.assertTrue(uniquelyRelatedNotices.contains(noticeLectures));
+		Assert.assertFalse(uniquelyRelatedNotices.contains(noticeEntries));
+	}
+	
+	/**
+	 * Lengthy test to check the method with more than a few notices
+	 * and cross check different cases.
+	 * 
+	 */
+	@Test
+	public void getAbsenceNoticeUniquelyRelatedTo_variant() {
+		Identity participant1 = JunitTestHelper.createAndPersistIdentityAsRndUser("noticee-1");
+		Identity participant2 = JunitTestHelper.createAndPersistIdentityAsRndUser("noticee-2");
+		Identity participant3 = JunitTestHelper.createAndPersistIdentityAsRndUser("noticee-3");
+		RepositoryEntry entry1 = JunitTestHelper.createAndPersistRepositoryEntry();
+		RepositoryEntry entry2 = JunitTestHelper.createAndPersistRepositoryEntry();
+
+		LectureBlock block1 = createMinimalLectureBlock(entry1);
+		LectureBlock block2 = createMinimalLectureBlock(entry1);
+		LectureBlock block3 = createMinimalLectureBlock(entry1);
+		LectureBlock block4 = createMinimalLectureBlock(entry2);
+		LectureBlock block5 = createMinimalLectureBlock(entry2);
+		LectureBlock block6 = createMinimalLectureBlock(entry2);
+		dbInstance.commit();
+
+		List<LectureBlock> lectureBlocks1_2 = new ArrayList<>();
+		lectureBlocks1_2.add(block1);
+		lectureBlocks1_2.add(block2);
+
+		AbsenceNotice notice1_2 = lectureService.createAbsenceNotice(participant1, AbsenceNoticeType.notified, AbsenceNoticeTarget.lectureblocks,
+				new Date(), new Date(), null, "1 2", null, null, lectureBlocks1_2, null);
+		
+		List<LectureBlock> lectureBlocks2_3_4 = new ArrayList<>();
+		lectureBlocks2_3_4.add(block2);
+		lectureBlocks2_3_4.add(block3);
+		lectureBlocks2_3_4.add(block4);
+		AbsenceNotice notice2_3_4 = lectureService.createAbsenceNotice(participant2, AbsenceNoticeType.notified, AbsenceNoticeTarget.lectureblocks,
+				new Date(), new Date(), null, "2 3 4", null, null, lectureBlocks2_3_4, null);
+		
+		List<LectureBlock> lectureBlocks1_3_4 = new ArrayList<>();
+		lectureBlocks1_3_4.add(block1);
+		lectureBlocks1_3_4.add(block3);
+		lectureBlocks1_3_4.add(block4);
+		AbsenceNotice notice1_3_4 = lectureService.createAbsenceNotice(participant3, AbsenceNoticeType.notified, AbsenceNoticeTarget.lectureblocks,
+				new Date(), new Date(), null, "1 3 4", null, null, lectureBlocks1_3_4, null);
+		
+		AbsenceNotice notice4 = lectureService.createAbsenceNotice(participant2, AbsenceNoticeType.notified, AbsenceNoticeTarget.lectureblocks,
+				new Date(), new Date(), null, "4", null, null, Collections.singletonList(block4), null);
+		
+		List<LectureBlock> lectureSecondBlocks4_5 = new ArrayList<>();
+		lectureSecondBlocks4_5.add(block4);
+		lectureSecondBlocks4_5.add(block5);
+		AbsenceNotice notice4_5 = lectureService.createAbsenceNotice(participant2, AbsenceNoticeType.notified, AbsenceNoticeTarget.lectureblocks,
+				new Date(), new Date(), null, "4 5", null, null, lectureSecondBlocks4_5, null);
+		
+		List<LectureBlock> lectureBlocks4_5_6 = new ArrayList<>();
+		lectureBlocks4_5_6.add(block4);
+		lectureBlocks4_5_6.add(block5);
+		lectureBlocks4_5_6.add(block6);
+		AbsenceNotice notice4_5_6 = lectureService.createAbsenceNotice(participant2, AbsenceNoticeType.notified, AbsenceNoticeTarget.lectureblocks,
+				new Date(), new Date(), null, "4 5 6", null, null, lectureBlocks4_5_6, null);
+		
+		AbsenceNotice notice6 = lectureService.createAbsenceNotice(participant2, AbsenceNoticeType.notified, AbsenceNoticeTarget.lectureblocks,
+				new Date(), new Date(), null, "6", null, null, Collections.singletonList(block6), null);
+		dbInstance.commit();
+		
+		
+		// check blocks 4, 5, 6
+		List<AbsenceNotice> uniquelyRelatedNotices4_5_6 = lectureService.getAbsenceNoticeUniquelyRelatedTo(lectureBlocks4_5_6);
+		Assert.assertNotNull(uniquelyRelatedNotices4_5_6);
+		Assert.assertEquals(4, uniquelyRelatedNotices4_5_6.size());
+		Assert.assertTrue(uniquelyRelatedNotices4_5_6.contains(notice4));
+		Assert.assertTrue(uniquelyRelatedNotices4_5_6.contains(notice4_5));
+		Assert.assertTrue(uniquelyRelatedNotices4_5_6.contains(notice4_5_6));
+		Assert.assertTrue(uniquelyRelatedNotices4_5_6.contains(notice6));
+		
+		// check blocks 1 5
+		List<LectureBlock> lectureBlocks1_5 = new ArrayList<>();
+		lectureBlocks1_5.add(block1);
+		lectureBlocks1_5.add(block3);
+		List<AbsenceNotice> uniquelyRelatedNotices1_5 = lectureService.getAbsenceNoticeUniquelyRelatedTo(lectureBlocks1_5);
+		Assert.assertNotNull(uniquelyRelatedNotices1_5);
+		Assert.assertTrue(uniquelyRelatedNotices1_5.isEmpty());
+		
+		// check blocks 1 2
+		lectureBlocks1_2.add(block1);// part of the test
+		lectureBlocks1_2.add(block2);
+		List<AbsenceNotice> uniquelyRelatedNotices1_2 = lectureService.getAbsenceNoticeUniquelyRelatedTo(lectureBlocks1_2);
+		Assert.assertNotNull(uniquelyRelatedNotices1_2);
+		Assert.assertEquals(1, uniquelyRelatedNotices1_2.size());
+		Assert.assertTrue(uniquelyRelatedNotices1_2.contains(notice1_2));
+		
+		// check blocks 4
+		List<LectureBlock> lectureBlocks4 = new ArrayList<>();
+		lectureBlocks4.add(block4);
+		List<AbsenceNotice> uniquelyRelatedNotices4 = lectureService.getAbsenceNoticeUniquelyRelatedTo(lectureBlocks4);
+		Assert.assertNotNull(uniquelyRelatedNotices4);
+		Assert.assertEquals(1, uniquelyRelatedNotices4.size());
+		Assert.assertTrue(uniquelyRelatedNotices4.contains(notice4));
+		
+		// check blocks 2, 3, 4, 5, 6
+		List<LectureBlock> lectureBlocks2_3_4_5_6 = new ArrayList<>();
+		lectureBlocks2_3_4_5_6.add(block2);
+		lectureBlocks2_3_4_5_6.add(block3);
+		lectureBlocks2_3_4_5_6.add(block4);
+		lectureBlocks2_3_4_5_6.add(block5);
+		lectureBlocks2_3_4_5_6.add(block6);
+		List<AbsenceNotice> uniquelyRelatedNotices2_3_4_5_6 = lectureService.getAbsenceNoticeUniquelyRelatedTo(lectureBlocks2_3_4_5_6);
+		Assert.assertNotNull(uniquelyRelatedNotices2_3_4_5_6);
+		Assert.assertEquals(5, uniquelyRelatedNotices2_3_4_5_6.size());
+		Assert.assertTrue(uniquelyRelatedNotices2_3_4_5_6.contains(notice2_3_4));
+		Assert.assertTrue(uniquelyRelatedNotices2_3_4_5_6.contains(notice4));
+		Assert.assertTrue(uniquelyRelatedNotices2_3_4_5_6.contains(notice4_5));
+		Assert.assertTrue(uniquelyRelatedNotices2_3_4_5_6.contains(notice4_5_6));
+		Assert.assertTrue(uniquelyRelatedNotices2_3_4_5_6.contains(notice6));
+		
+		// check all blocks
+		List<LectureBlock> lectureBlocks1_2_3_4_5_6 = new ArrayList<>();
+		lectureBlocks1_2_3_4_5_6.add(block1);
+		lectureBlocks1_2_3_4_5_6.add(block2);
+		lectureBlocks1_2_3_4_5_6.add(block3);
+		lectureBlocks1_2_3_4_5_6.add(block4);
+		lectureBlocks1_2_3_4_5_6.add(block5);
+		lectureBlocks1_2_3_4_5_6.add(block6);
+		List<AbsenceNotice> uniquelyRelatedNotices1_2_3_4_5_6 = lectureService.getAbsenceNoticeUniquelyRelatedTo(lectureBlocks1_2_3_4_5_6);
+		Assert.assertNotNull(uniquelyRelatedNotices1_2_3_4_5_6);
+		Assert.assertEquals(7, uniquelyRelatedNotices1_2_3_4_5_6.size());
+		Assert.assertTrue(uniquelyRelatedNotices1_2_3_4_5_6.contains(notice1_2));
+		Assert.assertTrue(uniquelyRelatedNotices1_2_3_4_5_6.contains(notice1_3_4));
+		Assert.assertTrue(uniquelyRelatedNotices1_2_3_4_5_6.contains(notice2_3_4));
+		Assert.assertTrue(uniquelyRelatedNotices1_2_3_4_5_6.contains(notice4));
+		Assert.assertTrue(uniquelyRelatedNotices1_2_3_4_5_6.contains(notice4_5));
+		Assert.assertTrue(uniquelyRelatedNotices1_2_3_4_5_6.contains(notice4_5_6));
+		Assert.assertTrue(uniquelyRelatedNotices1_2_3_4_5_6.contains(notice6));
+	}
+	
 	private LectureBlock createMinimalLectureBlock(RepositoryEntry entry) {
 		LectureBlock lectureBlock = lectureService.createLectureBlock(entry);
 		lectureBlock.setStartDate(new Date());