diff --git a/src/main/java/org/olat/modules/qpool/manager/QuestionPoolServiceImpl.java b/src/main/java/org/olat/modules/qpool/manager/QuestionPoolServiceImpl.java
index 1380350f3bcf176c1c8a67000b502fd678680e0b..442a0f66d775df4b3bcda72cdec066f4e6c7aae5 100644
--- a/src/main/java/org/olat/modules/qpool/manager/QuestionPoolServiceImpl.java
+++ b/src/main/java/org/olat/modules/qpool/manager/QuestionPoolServiceImpl.java
@@ -847,11 +847,13 @@ public class QuestionPoolServiceImpl implements QPoolService {
 
 	@Override
 	public TaxonomyLevel updateTaxonomyLevel(TaxonomyLevel level, String identifier, String displayName) {
-		return null;//taxonomy taxonomyLevelDao.updateTaxonomyLevel(level).update(newField, level);
+		level.setIdentifier(identifier);
+		level.setDisplayName(displayName);
+		return taxonomyLevelDao.updateTaxonomyLevel(level);
 	}
 
 	@Override
 	public boolean deleteTaxonomyLevel(TaxonomyLevel level) {
-		return false;//TODO taxonomy  taxonomyLevelDao.delete(level);
+		return taxonomyLevelDao.delete(level);
 	}
 }
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/taxonomy/TaxonomyService.java b/src/main/java/org/olat/modules/taxonomy/TaxonomyService.java
index 059ba632c64e84227f73d959f1d2aece51f48efe..b3939505f83094c118c4394f5c317df520d36546 100644
--- a/src/main/java/org/olat/modules/taxonomy/TaxonomyService.java
+++ b/src/main/java/org/olat/modules/taxonomy/TaxonomyService.java
@@ -53,23 +53,55 @@ public interface TaxonomyService {
 	public TaxonomyLevel createTaxonomyLevel(String identifier, String displayName, String description, String externalId,
 			TaxonomyLevelManagedFlag[] flags, TaxonomyLevel parent, Taxonomy taxonomy);
 	
+	/**
+	 * 
+	 * @return true if the level can be deleted
+	 */
+	public boolean deleteTaxonomyLevel(TaxonomyLevelRef taxonomyLevel);
+	
 	/**
 	 * @param ref The root taxonomy (optional)
 	 * @return A list of levels
 	 */
 	public List<TaxonomyLevel> getTaxonomyLevels(TaxonomyRef ref);
 	
+	/**
+	 * Load a taxonomy level by is reference.
+	 * 
+	 * @param ref The taxonomy level key
+	 * @return The freshly loaded taxonomy level
+	 */
 	public TaxonomyLevel getTaxonomyLevel(TaxonomyLevelRef ref);
 	
+	
 	public List<TaxonomyLevel> getTaxonomyLevelParentLine(TaxonomyLevel taxonomyLevel, Taxonomy taxonomy);
 	
 	public TaxonomyLevel updateTaxonomyLevel(TaxonomyLevel level);
 	
-	
+	/**
+	 * Get the documents directory for the specified taxonomy level.
+	 * 
+	 * @param level The taxonomy level
+	 * @return A directory
+	 */
 	public VFSContainer getDocumentsLibrary(TaxonomyLevel level);
 	
+	/**
+	 * Get the documents library for the specified taxonomy.
+	 * 
+	 * @param taxonomy The taxonomy
+	 * @return A directory
+	 */
 	public VFSContainer getDocumentsLibrary(Taxonomy taxonomy);
 	
+	/**
+	 * The directory reserved to the information page of the
+	 * taxonomy. The info page itself is normally "index.html"
+	 * and the directory can be used to save some images.
+	 * 
+	 * @param taxonomy The taxonomy
+	 * @return A directory
+	 */
 	public VFSContainer getTaxonomyInfoPageContainer(Taxonomy taxonomy);
 	
 	
@@ -181,6 +213,13 @@ public interface TaxonomyService {
 			TaxonomyRef taxonomy, TaxonomyCompetence competence,
 			IdentityRef assessedIdentity, IdentityRef author);
 	
+	/**
+	 * Standardized conversion from object to XML used by
+	 * the audit log.
+	 * 
+	 * @param competence The competence
+	 * @return A XML representation of the competence.
+	 */
 	public String toAuditXml(TaxonomyCompetence competence);
 
 }
diff --git a/src/main/java/org/olat/modules/taxonomy/manager/TaxonomyLevelDAO.java b/src/main/java/org/olat/modules/taxonomy/manager/TaxonomyLevelDAO.java
index fc10109c651e088e635d4ecfb4c4ee0fa81b6c47..37a76920bb4cc4e869a31812289f50ca3fddbf0b 100644
--- a/src/main/java/org/olat/modules/taxonomy/manager/TaxonomyLevelDAO.java
+++ b/src/main/java/org/olat/modules/taxonomy/manager/TaxonomyLevelDAO.java
@@ -36,6 +36,7 @@ import org.olat.core.util.vfs.VFSContainer;
 import org.olat.modules.taxonomy.Taxonomy;
 import org.olat.modules.taxonomy.TaxonomyLevel;
 import org.olat.modules.taxonomy.TaxonomyLevelManagedFlag;
+import org.olat.modules.taxonomy.TaxonomyLevelRef;
 import org.olat.modules.taxonomy.TaxonomyLevelType;
 import org.olat.modules.taxonomy.TaxonomyRef;
 import org.olat.modules.taxonomy.model.TaxonomyLevelImpl;
@@ -92,28 +93,39 @@ public class TaxonomyLevelDAO implements InitializingBean {
 		String storage = createLevelStorage(taxonomy, level);
 		level.setDirectoryPath(storage);
 		
+		String identifiersPath = getMaterializedPathIdentifiers(parent, level);
+		String keysPath = getMaterializedPathKeys(parent, level);
+		level.setParent(parent);
+		level.setMaterializedPathKeys(keysPath);
+		level.setMaterializedPathIdentifiers(identifiersPath);
+
+		level = dbInstance.getCurrentEntityManager().merge(level);
+		level.getTaxonomy();
+		return level;
+	}
+	
+	private String getMaterializedPathIdentifiers(TaxonomyLevel parent, TaxonomyLevel level) {
 		if(parent != null) {
-			level.setParent(parent);
-			
-			String parentPathOfKeys = ((TaxonomyLevelImpl)parent).getMaterializedPathKeys();
+			String parentPathOfIdentifiers = parent.getMaterializedPathIdentifiers();
+			if(parentPathOfIdentifiers == null || "/".equals(parentPathOfIdentifiers)) {
+				parentPathOfIdentifiers = "/";
+			}
+			return parentPathOfIdentifiers + level.getIdentifier()  + "/";
+		}
+		return "/" + level.getIdentifier()  + "/";
+	}
+	
+	private String getMaterializedPathKeys(TaxonomyLevel parent, TaxonomyLevel level) {
+		if(parent != null) {
+
+			String parentPathOfKeys = parent.getMaterializedPathKeys();
 			if(parentPathOfKeys == null || "/".equals(parentPathOfKeys)) {
 				parentPathOfKeys = "";
 			}
-			String parentPathOfIdentifiers = ((TaxonomyLevelImpl)parent).getMaterializedPathIdentifiers();
-			if(parentPathOfIdentifiers == null || "/".equals(parentPathOfIdentifiers)) {
-				parentPathOfIdentifiers = "";
-			}
 
-			level.setMaterializedPathKeys(parentPathOfKeys + level.getKey() + "/");
-			level.setMaterializedPathIdentifiers(parentPathOfIdentifiers + level.getIdentifier()  + "/");
-		} else {
-			level.setMaterializedPathKeys("/" + level.getKey() + "/");
-			level.setMaterializedPathIdentifiers("/" + level.getIdentifier()  + "/");
+			return parentPathOfKeys + level.getKey() + "/";
 		}
-
-		level = dbInstance.getCurrentEntityManager().merge(level);
-		level.getTaxonomy();
-		return level;
+		return "/" + level.getKey() + "/";
 	}
 	
 	public TaxonomyLevel loadByKey(Long key) {
@@ -171,8 +183,19 @@ public class TaxonomyLevelDAO implements InitializingBean {
 			.getResultList();
 	}
 	
+	public TaxonomyLevel getParent(TaxonomyLevelRef taxonomyLevel) {
+		StringBuilder sb = new StringBuilder(256);
+		sb.append("select level.parent from ctaxonomylevel as level")
+		  .append(" where level.key=:taxonomyLevelKey");
+		List<TaxonomyLevel> levels = dbInstance.getCurrentEntityManager()
+				.createQuery(sb.toString(), TaxonomyLevel.class)
+				.setParameter("taxonomyLevelKey", taxonomyLevel.getKey())
+				.getResultList();
+		return levels == null || levels.isEmpty() ? null : levels.get(0);
+	}
+	
 	// Perhaps replace it with a select in ( materializedPathKeys.split("[/]") ) would be better
-	public List<TaxonomyLevel> getParentLine(TaxonomyLevel taxonomyLevel, Taxonomy taxonomy) {
+	public List<TaxonomyLevel> getParentLine(TaxonomyLevel taxonomyLevel, TaxonomyRef taxonomy) {
 		StringBuilder sb = new StringBuilder(256);
 		sb.append("select level from ctaxonomylevel as level")
 		  .append(" left join fetch level.parent as parent")
@@ -189,9 +212,99 @@ public class TaxonomyLevelDAO implements InitializingBean {
 		return levels;
 	}
 	
+	public List<TaxonomyLevel> getDescendants(TaxonomyLevel taxonomyLevel, TaxonomyRef taxonomy) {
+		StringBuilder sb = new StringBuilder(256);
+		sb.append("select level from ctaxonomylevel as level")
+		  .append(" left join fetch level.parent as parent")
+		  .append(" left join fetch level.type as type")
+		  .append(" where level.taxonomy.key=:taxonomyKey")
+		  .append(" and level.key!=:levelKey and level.materializedPathKeys like :materializedPath");
+		  
+		List<TaxonomyLevel> levels = dbInstance.getCurrentEntityManager()
+			.createQuery(sb.toString(), TaxonomyLevel.class)
+			.setParameter("materializedPath", taxonomyLevel.getMaterializedPathKeys() + "%")
+			.setParameter("levelKey", taxonomyLevel.getKey())
+			.setParameter("taxonomyKey", taxonomy.getKey())
+			.getResultList();
+		Collections.sort(levels, new PathMaterializedPathLengthComparator());
+		return levels;
+	}
+	
 	public TaxonomyLevel updateTaxonomyLevel(TaxonomyLevel level) {
+		boolean updatePath = false;
+		
+		String path = level.getMaterializedPathIdentifiers();
+		String newPath = null;
+		
+		TaxonomyLevel parentLevel = getParent(level);
+		if(parentLevel != null) {
+			newPath = getMaterializedPathIdentifiers(parentLevel, level);
+			updatePath = !newPath.equals(path);
+			if(updatePath) {
+				((TaxonomyLevelImpl)level).setMaterializedPathIdentifiers(newPath);
+			}
+		}
+
 		((TaxonomyLevelImpl)level).setLastModified(new Date());
-		return dbInstance.getCurrentEntityManager().merge(level);
+		TaxonomyLevel mergedLevel = dbInstance.getCurrentEntityManager().merge(level);
+		
+		if(updatePath) {
+			List<TaxonomyLevel> descendants = getDescendants(mergedLevel, mergedLevel.getTaxonomy());
+			for(TaxonomyLevel descendant:descendants) {
+				String descendantPath = descendant.getMaterializedPathIdentifiers();
+				if(descendantPath.indexOf(path) == 0) {
+					String end = descendantPath.substring(path.length(), descendantPath.length());
+					String updatedPath = newPath + end;
+					((TaxonomyLevelImpl)descendant).setMaterializedPathIdentifiers(updatedPath);
+				}
+				dbInstance.getCurrentEntityManager().merge(descendant);
+			}
+		}
+		return mergedLevel;
+	}
+	
+	public boolean delete(TaxonomyLevelRef taxonomyLevel) {
+		if(!hasChildren(taxonomyLevel) && !hasItemUsing(taxonomyLevel) &&!hasCompetenceUsing(taxonomyLevel)) {
+			TaxonomyLevel impl = loadByKey(taxonomyLevel.getKey());
+			if(impl != null) {
+				dbInstance.getCurrentEntityManager().remove(impl);
+			}
+			return true;
+		}
+		return false;
+	}
+	
+	public boolean hasItemUsing(TaxonomyLevelRef taxonomyLevel) {
+		String sb = "select item.key from questionitem item where item.taxonomyLevel.key=:taxonomyLevelKey";
+		List<Long> items = dbInstance.getCurrentEntityManager()
+				.createQuery(sb.toString(), Long.class)
+				.setParameter("taxonomyLevelKey", taxonomyLevel.getKey())
+				.setFirstResult(0)
+				.setMaxResults(1)
+				.getResultList();
+		return items != null && items.size() > 0 && items.get(0) != null && items.get(0).intValue() > 0;
+	}
+	
+	public boolean hasCompetenceUsing(TaxonomyLevelRef taxonomyLevel) {
+		String sb = "select competence.key from ctaxonomycompetence competence where competence.taxonomyLevel.key=:taxonomyLevelKey";
+		List<Long> comptences = dbInstance.getCurrentEntityManager()
+				.createQuery(sb.toString(), Long.class)
+				.setParameter("taxonomyLevelKey", taxonomyLevel.getKey())
+				.setFirstResult(0)
+				.setMaxResults(1)
+				.getResultList();
+		return comptences != null && comptences.size() > 0 && comptences.get(0) != null && comptences.get(0).intValue() > 0;
+	}
+	
+	public boolean hasChildren(TaxonomyLevelRef taxonomyLevel) {
+		String sb = "select level.key from ctaxonomylevel as level where level.parent.key=:taxonomyLevelKey";
+		List<Long> children = dbInstance.getCurrentEntityManager()
+			.createQuery(sb.toString(), Long.class)
+			.setParameter("taxonomyLevelKey", taxonomyLevel.getKey())
+			.setFirstResult(0)
+			.setMaxResults(1)
+			.getResultList();
+		return children != null && children.size() > 0 && children.get(0) != null && children.get(0).intValue() > 0;
 	}
 	
 	public VFSContainer getDocumentsLibrary(TaxonomyLevel level) {
diff --git a/src/main/java/org/olat/modules/taxonomy/manager/TaxonomyServiceImpl.java b/src/main/java/org/olat/modules/taxonomy/manager/TaxonomyServiceImpl.java
index e1bd4b0a628c9ffa8c07faef35441e30b3f31d71..e23ebb543b04ba2be4d354df31848ce9b46c7781 100644
--- a/src/main/java/org/olat/modules/taxonomy/manager/TaxonomyServiceImpl.java
+++ b/src/main/java/org/olat/modules/taxonomy/manager/TaxonomyServiceImpl.java
@@ -120,6 +120,11 @@ public class TaxonomyServiceImpl implements TaxonomyService {
 		return taxonomyLevelDao.updateTaxonomyLevel(level);
 	}
 
+	@Override
+	public boolean deleteTaxonomyLevel(TaxonomyLevelRef taxonomyLevel) {
+		return taxonomyLevelDao.delete(taxonomyLevel);
+	}
+
 	@Override
 	public VFSContainer getDocumentsLibrary(TaxonomyLevel level) {
 		return taxonomyLevelDao.getDocumentsLibrary(level);
diff --git a/src/test/java/org/olat/modules/taxonomy/manager/TaxonomyLevelDAOTest.java b/src/test/java/org/olat/modules/taxonomy/manager/TaxonomyLevelDAOTest.java
index c00403a398fbfd39a1cccda356c558423ee631a9..f81f1752d262284a09d8b23d760b3ff3d7719cd5 100644
--- a/src/test/java/org/olat/modules/taxonomy/manager/TaxonomyLevelDAOTest.java
+++ b/src/test/java/org/olat/modules/taxonomy/manager/TaxonomyLevelDAOTest.java
@@ -153,6 +153,24 @@ public class TaxonomyLevelDAOTest extends OlatTestCase {
 		Assert.assertEquals(level_5, levels.get(4));
 	}
 	
+	@Test
+	public void getDescendants() {
+		Taxonomy taxonomy = taxonomyDao.createTaxonomy("ID-103b", "Deeply leveled taxonomy", null, null);
+		TaxonomyLevel level_1 = taxonomyLevelDao.createTaxonomyLevel("L-1", "A level", "A basic level", null, null, null, null, taxonomy);
+		TaxonomyLevel level_2 = taxonomyLevelDao.createTaxonomyLevel("L-2", "A level", "A basic level", null, null, level_1, null, taxonomy);
+		TaxonomyLevel level_3 = taxonomyLevelDao.createTaxonomyLevel("L-3", "A level", "A basic level", null, null, level_2, null, taxonomy);
+		TaxonomyLevel level_4 = taxonomyLevelDao.createTaxonomyLevel("L-4", "A level", "A basic level", null, null, level_3, null, taxonomy);
+		TaxonomyLevel level_5 = taxonomyLevelDao.createTaxonomyLevel("L-5", "A level", "A basic level", null, null, level_4, null, taxonomy);
+		dbInstance.commit();
+
+		List<TaxonomyLevel> levels = taxonomyLevelDao.getDescendants(level_2, taxonomy);
+		Assert.assertNotNull(levels);
+		Assert.assertEquals(3, levels.size());
+		Assert.assertTrue(levels.contains(level_3));
+		Assert.assertTrue(levels.contains(level_4));
+		Assert.assertTrue(levels.contains(level_5));
+	}
+	
 	@Test
 	public void getLevelsByExternalId() {
 		Taxonomy taxonomy = taxonomyDao.createTaxonomy("ID-103", "Externalized taxonomy", null, null);
@@ -178,4 +196,56 @@ public class TaxonomyLevelDAOTest extends OlatTestCase {
 		Assert.assertEquals(1, levels.size());
 		Assert.assertEquals(level, levels.get(0));
 	}
+	
+	@Test
+	public void updateTaxonomyLevel_simple() {
+		Taxonomy taxonomy = taxonomyDao.createTaxonomy("ID-105", "Updated taxonomy", null, null);
+		String displayName = UUID.randomUUID().toString();
+		TaxonomyLevel level1 = taxonomyLevelDao.createTaxonomyLevel("U-1", displayName, "A basic level", null, null, null, null, taxonomy);
+		TaxonomyLevel level2 = taxonomyLevelDao.createTaxonomyLevel("U-2", displayName, "A basic level", null, null, level1, null, taxonomy);
+		dbInstance.commitAndCloseSession();
+		
+		TaxonomyLevel reloadedLevel2 = taxonomyLevelDao.loadByKey(level2.getKey());
+		reloadedLevel2.setDisplayName("Updated");
+		reloadedLevel2.setIdentifier("UU");
+		TaxonomyLevel updatedLevel2 = taxonomyLevelDao.updateTaxonomyLevel(reloadedLevel2);
+		dbInstance.commitAndCloseSession();
+		
+		String identifiersPath = updatedLevel2.getMaterializedPathIdentifiers();
+		Assert.assertEquals("/U-1/UU/", identifiersPath);
+	}
+	
+	@Test
+	public void updateTaxonomyLevel_withChildren() {
+		Taxonomy taxonomy = taxonomyDao.createTaxonomy("ID-105", "Updated taxonomy", null, null);
+		String displayName = UUID.randomUUID().toString();
+		TaxonomyLevel level1 = taxonomyLevelDao.createTaxonomyLevel("U-1", displayName, "A basic level", null, null, null, null, taxonomy);
+		TaxonomyLevel level2 = taxonomyLevelDao.createTaxonomyLevel("U-2", displayName, "A basic level", null, null, level1, null, taxonomy);
+		TaxonomyLevel level3 = taxonomyLevelDao.createTaxonomyLevel("U-3", displayName, "A basic level", null, null, level2, null, taxonomy);
+		TaxonomyLevel level4_1 = taxonomyLevelDao.createTaxonomyLevel("U-4-1", displayName, "A basic level", null, null, level3, null, taxonomy);
+		TaxonomyLevel level4_2 = taxonomyLevelDao.createTaxonomyLevel("U-4-2", displayName, "A basic level", null, null, level3, null, taxonomy);
+		dbInstance.commitAndCloseSession();
+		
+		TaxonomyLevel reloadedLevel2 = taxonomyLevelDao.loadByKey(level2.getKey());
+		reloadedLevel2.setDisplayName("Updated");
+		reloadedLevel2.setIdentifier("UBU");
+		TaxonomyLevel updatedLevel2 = taxonomyLevelDao.updateTaxonomyLevel(reloadedLevel2);
+		dbInstance.commitAndCloseSession();
+		
+		//check the different levels
+		String identifiersPath2 = updatedLevel2.getMaterializedPathIdentifiers();
+		Assert.assertEquals("/U-1/UBU/", identifiersPath2);
+
+		TaxonomyLevel updatedLevel3 = taxonomyLevelDao.loadByKey(level3.getKey());
+		String identifiersPath3 = updatedLevel3.getMaterializedPathIdentifiers();
+		Assert.assertEquals("/U-1/UBU/U-3/", identifiersPath3);
+
+		TaxonomyLevel updatedLevel4_1 = taxonomyLevelDao.loadByKey(level4_1.getKey());
+		String identifiersPath4_1 = updatedLevel4_1.getMaterializedPathIdentifiers();
+		Assert.assertEquals("/U-1/UBU/U-3/U-4-1/", identifiersPath4_1);
+		
+		TaxonomyLevel updatedLevel4_2 = taxonomyLevelDao.loadByKey(level4_2.getKey());
+		String identifiersPath4_2 = updatedLevel4_2.getMaterializedPathIdentifiers();
+		Assert.assertEquals("/U-1/UBU/U-3/U-4-2/", identifiersPath4_2);
+	}
 }