From 4d18281d0ddc66d13ede3d4fe6b125b1dae0db55 Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Thu, 28 Feb 2013 13:39:45 +0100
Subject: [PATCH] OO-535: more stuff in admin...

---
 .../table/FlexiTableClassicRenderer.java      |   3 +-
 .../java/org/olat/modules/qpool/Pool.java     |   2 +
 .../modules/qpool/QuestionPoolService.java    |  17 ++
 .../org/olat/modules/qpool/StudyField.java    |   2 +
 .../impl/PdfQuestionPoolServiceProvider.java  |  13 +-
 .../impl/TextQuestionPoolServiceProvider.java |   7 +-
 .../modules/qpool/manager/CollectionDAO.java  |  20 +-
 .../qpool/manager/NullPoolService.java        |   2 +-
 .../olat/modules/qpool/manager/PoolDAO.java   |  49 ++++-
 .../qpool/manager/QuestionItemDAO.java        |  21 +-
 .../manager/QuestionPoolServiceImpl.java      |  43 +++-
 .../modules/qpool/manager/StudyFieldDAO.java  |   3 +-
 .../modules/qpool/model/CollectionToItem.java |   7 +-
 .../olat/modules/qpool/model/PoolImpl.java    |  28 +++
 .../modules/qpool/model/QuestionItemImpl.java |  17 +-
 .../qpool/ui/CreateCollectionController.java  |   2 +-
 .../qpool/ui/FilePreviewController.java       |  65 ++++++
 .../olat/modules/qpool/ui/PoolDataModel.java  | 130 +++++++++++
 .../modules/qpool/ui/PoolEditController.java  |  97 ++++++++
 .../org/olat/modules/qpool/ui/PoolRow.java    |  49 +++++
 .../qpool/ui/PoolsAdminController.java        | 207 ++++++++++++++++++
 .../org/olat/modules/qpool/ui/QPoolEvent.java |   2 +
 .../ui/QuestionPoolMainEditorController.java  |  51 ++++-
 .../qpool/ui/StudyFieldAdminController.java   |  15 ++
 .../modules/qpool/ui/StudyFieldTreeModel.java |  78 +++++++
 .../qpool/ui/TextPreviewController.java       |  98 +++++++++
 .../qpool/ui/_content/admin_study_fields.html |   2 +
 .../qpool/ui/_content/file_preview.html       |   1 +
 .../qpool/ui/_content/pools_admin.html        |  14 ++
 .../qpool/ui/_content/text_preview.html       |   1 +
 .../qpool/ui/_i18n/LocalStrings_de.properties |   7 +
 .../java/org/olat/search/SearchService.java   |   4 +-
 .../search/service/SearchServiceImpl.java     |   5 +-
 .../service/indexer/QuestionItemIndexer.java  |  19 ++
 .../database/mysql/alter_8_4_0_to_9_0_0.sql   |  10 +-
 .../FileResourceValidatorTest.java            |  19 ++
 .../modules/qpool/manager/PoolDAOTest.java    |   2 +-
 37 files changed, 1048 insertions(+), 64 deletions(-)
 create mode 100644 src/main/java/org/olat/modules/qpool/ui/FilePreviewController.java
 create mode 100644 src/main/java/org/olat/modules/qpool/ui/PoolDataModel.java
 create mode 100644 src/main/java/org/olat/modules/qpool/ui/PoolEditController.java
 create mode 100644 src/main/java/org/olat/modules/qpool/ui/PoolRow.java
 create mode 100644 src/main/java/org/olat/modules/qpool/ui/PoolsAdminController.java
 create mode 100644 src/main/java/org/olat/modules/qpool/ui/StudyFieldTreeModel.java
 create mode 100644 src/main/java/org/olat/modules/qpool/ui/TextPreviewController.java
 create mode 100644 src/main/java/org/olat/modules/qpool/ui/_content/file_preview.html
 create mode 100644 src/main/java/org/olat/modules/qpool/ui/_content/pools_admin.html
 create mode 100644 src/main/java/org/olat/modules/qpool/ui/_content/text_preview.html

diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableClassicRenderer.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableClassicRenderer.java
index fd8cdab350e..c67e7224d0f 100644
--- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableClassicRenderer.java
+++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableClassicRenderer.java
@@ -78,7 +78,8 @@ class FlexiTableClassicRenderer implements ComponentRenderer {
 		// build rows
 		target.append("<tbody>");
 		// the really selected rowid (from the tabledatamodel)
-		
+
+		dataModel.load(0, rows);
 		for (int i = 0; i < rows; i++) {
 			// use alternating css class
 			String cssClass;
diff --git a/src/main/java/org/olat/modules/qpool/Pool.java b/src/main/java/org/olat/modules/qpool/Pool.java
index 168350f8a19..06ace8a52f5 100644
--- a/src/main/java/org/olat/modules/qpool/Pool.java
+++ b/src/main/java/org/olat/modules/qpool/Pool.java
@@ -36,5 +36,7 @@ public interface Pool {
 	public Date getLastModified();
 	
 	public String getName();
+	
+	public void setName(String name);
 
 }
diff --git a/src/main/java/org/olat/modules/qpool/QuestionPoolService.java b/src/main/java/org/olat/modules/qpool/QuestionPoolService.java
index 43819bf5310..dcb24f125f7 100644
--- a/src/main/java/org/olat/modules/qpool/QuestionPoolService.java
+++ b/src/main/java/org/olat/modules/qpool/QuestionPoolService.java
@@ -96,4 +96,21 @@ public interface QuestionPoolService {
 	
 	public List<QuestionItem> getItemsOfCollection(QuestionItemCollection collection, int firstResult, int maxResults, SortKey... orderBy);
 
+	
+	//study field admin
+	public List<StudyField> getStudyFields();
+	
+	
+	//pool administration
+	public void createPool(Identity identity, String name);
+	
+	public Pool updatePool(Pool pool);
+	
+	public void deletePool(Pool pool);
+	
+	public int countPools();
+
+	public List<Pool> getPools(int firstResult, int maxResults, SortKey... orderBy);
+	
+	
 }
diff --git a/src/main/java/org/olat/modules/qpool/StudyField.java b/src/main/java/org/olat/modules/qpool/StudyField.java
index 098e926cb0c..6ae0a755460 100644
--- a/src/main/java/org/olat/modules/qpool/StudyField.java
+++ b/src/main/java/org/olat/modules/qpool/StudyField.java
@@ -36,4 +36,6 @@ public interface StudyField {
 	public Date getLastModified();
 	
 	public String getField();
+	
+	public StudyField getParentField();
 }
diff --git a/src/main/java/org/olat/modules/qpool/impl/PdfQuestionPoolServiceProvider.java b/src/main/java/org/olat/modules/qpool/impl/PdfQuestionPoolServiceProvider.java
index 87e64c5631b..1d315ebe781 100644
--- a/src/main/java/org/olat/modules/qpool/impl/PdfQuestionPoolServiceProvider.java
+++ b/src/main/java/org/olat/modules/qpool/impl/PdfQuestionPoolServiceProvider.java
@@ -27,6 +27,7 @@ import org.olat.core.gui.control.WindowControl;
 import org.olat.core.util.vfs.VFSLeaf;
 import org.olat.modules.qpool.QuestionItem;
 import org.olat.modules.qpool.QuestionPoolSPI;
+import org.olat.modules.qpool.ui.FilePreviewController;
 
 /**
  * 
@@ -62,15 +63,13 @@ public class PdfQuestionPoolServiceProvider implements QuestionPoolSPI {
 
 	@Override
 	public Controller getPreviewController(UserRequest ureq, WindowControl wControl, QuestionItem item) {
-		return null;
+		FilePreviewController fileController = new FilePreviewController(ureq, wControl, item);
+		return fileController;
 	}
 
 	@Override
 	public Controller getEditableController(UserRequest ureq,	WindowControl wControl, QuestionItem item) {
-		return null;
+		FilePreviewController fileController = new FilePreviewController(ureq, wControl, item);
+		return fileController;
 	}
-
-
-	
-
-}
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/qpool/impl/TextQuestionPoolServiceProvider.java b/src/main/java/org/olat/modules/qpool/impl/TextQuestionPoolServiceProvider.java
index efd6b386755..43b3fa82978 100644
--- a/src/main/java/org/olat/modules/qpool/impl/TextQuestionPoolServiceProvider.java
+++ b/src/main/java/org/olat/modules/qpool/impl/TextQuestionPoolServiceProvider.java
@@ -27,6 +27,7 @@ import org.olat.core.gui.control.WindowControl;
 import org.olat.core.util.vfs.VFSLeaf;
 import org.olat.modules.qpool.QuestionItem;
 import org.olat.modules.qpool.QuestionPoolSPI;
+import org.olat.modules.qpool.ui.TextPreviewController;
 
 /**
  * 
@@ -60,11 +61,13 @@ public class TextQuestionPoolServiceProvider implements QuestionPoolSPI {
 
 	@Override
 	public Controller getPreviewController(UserRequest ureq, WindowControl wControl, QuestionItem item) {
-		return null;
+		TextPreviewController txtController = new TextPreviewController(ureq, wControl, item);
+		return txtController;
 	}
 
 	@Override
 	public Controller getEditableController(UserRequest ureq, WindowControl wControl, QuestionItem item) {
-		return null;
+		TextPreviewController txtController = new TextPreviewController(ureq, wControl, item);
+		return txtController;
 	}
 }
diff --git a/src/main/java/org/olat/modules/qpool/manager/CollectionDAO.java b/src/main/java/org/olat/modules/qpool/manager/CollectionDAO.java
index 4de4ac4a60f..8e47f2accb1 100644
--- a/src/main/java/org/olat/modules/qpool/manager/CollectionDAO.java
+++ b/src/main/java/org/olat/modules/qpool/manager/CollectionDAO.java
@@ -19,6 +19,7 @@
  */
 package org.olat.modules.qpool.manager;
 
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 
@@ -32,6 +33,7 @@ import org.olat.modules.qpool.QuestionItem;
 import org.olat.modules.qpool.QuestionItemCollection;
 import org.olat.modules.qpool.model.CollectionToItem;
 import org.olat.modules.qpool.model.QuestionItemCollectionImpl;
+import org.olat.modules.qpool.model.QuestionItemImpl;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -73,7 +75,7 @@ public class CollectionDAO {
 	}
 	
 	public void addItemToCollection(QuestionItem item, QuestionItemCollection collection) {
-		QuestionItem lockedItem = questionItemDao.loadForUpdate(item.getKey());
+		QuestionItemImpl lockedItem = questionItemDao.loadForUpdate(item.getKey());
 		if(!isInCollection(collection, lockedItem)) {
 			CollectionToItem coll2Item = new CollectionToItem();
 			coll2Item.setCreationDate(new Date());
@@ -84,7 +86,7 @@ public class CollectionDAO {
 		dbInstance.commit();
 	}
 	
-	public boolean isInCollection(QuestionItemCollection collection, QuestionItem item) {
+	public boolean isInCollection(QuestionItemCollection collection, QuestionItemImpl item) {
 		StringBuilder sb = new StringBuilder();
 		sb.append("select count(coll2item) from qcollection2item coll2item where coll2item.collection.key=:collectionKey and coll2item.item.key=:itemKey");
 		Number count = dbInstance.getCurrentEntityManager()
@@ -131,4 +133,18 @@ public class CollectionDAO {
 				.setParameter("identityKey", me.getKey())
 				.getResultList();
 	}
+	
+	public int deleteItemFromCollections(List<QuestionItem> items) {
+		List<Long> keys = new ArrayList<Long>();
+		for(QuestionItem item:items) {
+			keys.add(item.getKey());
+		}
+		
+		StringBuilder sb = new StringBuilder();
+		sb.append("delete from qcollection2item coll2item where coll2item.item.key in (:itemKeys)");
+		return dbInstance.getCurrentEntityManager()
+				.createQuery(sb.toString())
+				.setParameter("itemKeys", keys)
+				.executeUpdate();
+	}
 }
diff --git a/src/main/java/org/olat/modules/qpool/manager/NullPoolService.java b/src/main/java/org/olat/modules/qpool/manager/NullPoolService.java
index 685691003ba..6bacf5973ce 100644
--- a/src/main/java/org/olat/modules/qpool/manager/NullPoolService.java
+++ b/src/main/java/org/olat/modules/qpool/manager/NullPoolService.java
@@ -90,7 +90,7 @@ public class NullPoolService implements ApplicationListener<ContextRefreshedEven
 
 		int numOfQuestions = questionItemDao.getNumOfQuestions();
 		if(numOfQuestions < 3) {
-			List<Pool> pools = poolDao.getPools();
+			List<Pool> pools = poolDao.getPools(0, -1);
 			for(int i=0; i<200; i++) {
 				long randomIndex = Math.round(Math.random() * (fields.size() - 1));
 				StudyField field = fields.get((int)randomIndex);
diff --git a/src/main/java/org/olat/modules/qpool/manager/PoolDAO.java b/src/main/java/org/olat/modules/qpool/manager/PoolDAO.java
index bc75a34b800..8f241341c59 100644
--- a/src/main/java/org/olat/modules/qpool/manager/PoolDAO.java
+++ b/src/main/java/org/olat/modules/qpool/manager/PoolDAO.java
@@ -25,6 +25,8 @@ import java.util.List;
 
 import javax.persistence.TypedQuery;
 
+import org.olat.basesecurity.BaseSecurity;
+import org.olat.basesecurity.SecurityGroup;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.commons.persistence.PersistenceHelper;
 import org.olat.core.commons.persistence.SortKey;
@@ -48,13 +50,18 @@ public class PoolDAO {
 	private DB dbInstance;
 	@Autowired
 	private QuestionItemDAO questionItemDao;
+	@Autowired
+	private BaseSecurity securityManager;
 	
-	
-	public Pool createPool(String name) {
+	public PoolImpl createPool(String name) {
 		PoolImpl pool = new PoolImpl();
 		pool.setCreationDate(new Date());
 		pool.setLastModified(new Date());
 		pool.setName(name);
+		SecurityGroup ownerGroup = securityManager.createAndPersistSecurityGroup();
+		pool.setOwnerGroup(ownerGroup);
+		SecurityGroup participantGroup = securityManager.createAndPersistSecurityGroup();
+		pool.setParticipantGroup(participantGroup);
 		dbInstance.getCurrentEntityManager().persist(pool);
 		return pool;
 	}
@@ -73,6 +80,22 @@ public class PoolDAO {
 				.executeUpdate();
 	}
 	
+	public Pool updatePool(Pool pool) {
+		return dbInstance.getCurrentEntityManager().merge(pool);
+	}
+	
+	public void deletePool(Pool pool) {
+		StringBuilder sb = new StringBuilder();
+		sb.append("delete from qpool2item pool2item where pool2item.pool.key=:poolKey");
+		dbInstance.getCurrentEntityManager()
+				.createQuery(sb.toString())
+				.setParameter("poolKey", pool.getKey())
+				.executeUpdate();
+		
+		PoolImpl poolRef = dbInstance.getCurrentEntityManager().getReference(PoolImpl.class, pool.getKey());
+		dbInstance.getCurrentEntityManager().remove(poolRef);
+	}
+	
 	public int getNumOfPools() {
 		StringBuilder sb = new StringBuilder();
 		sb.append("select count(pool) from qpool pool");
@@ -81,13 +104,27 @@ public class PoolDAO {
 				.getSingleResult().intValue();
 	}
 	
-	public List<Pool> getPools() {
+	public int countPools() {
+		StringBuilder sb = new StringBuilder();
+		sb.append("select count(pool) from qpool pool");
+		return dbInstance.getCurrentEntityManager()
+				.createQuery(sb.toString(), Number.class)
+				.getSingleResult().intValue();
+	}
+	
+	public List<Pool> getPools(int firstResult, int maxResults) {
 		StringBuilder sb = new StringBuilder();
 		sb.append("select pool from qpool pool");
 		
-		return dbInstance.getCurrentEntityManager()
-				.createQuery(sb.toString(), Pool.class)
-				.getResultList();
+		TypedQuery<Pool> query = dbInstance.getCurrentEntityManager()
+				.createQuery(sb.toString(), Pool.class);
+		if(firstResult >= 0) {
+			query.setFirstResult(firstResult);
+		}
+		if(maxResults > 0) {
+			query.setMaxResults(maxResults);
+		}
+		return query.getResultList();
 	}
 	
 	public void addItemToPool(QuestionItem item, Pool pool) {
diff --git a/src/main/java/org/olat/modules/qpool/manager/QuestionItemDAO.java b/src/main/java/org/olat/modules/qpool/manager/QuestionItemDAO.java
index 935de6092c2..48c27536530 100644
--- a/src/main/java/org/olat/modules/qpool/manager/QuestionItemDAO.java
+++ b/src/main/java/org/olat/modules/qpool/manager/QuestionItemDAO.java
@@ -87,11 +87,11 @@ public class QuestionItemDAO {
 		item.setStudyField(field);
 		item.setDirectory(generateDir(uuid));
 		item.setRootFilename(rootFilename);
-		SecurityGroup authorGroup = securityManager.createAndPersistSecurityGroup();
-		item.setAuthorGroup(authorGroup);
+		SecurityGroup ownerGroup = securityManager.createAndPersistSecurityGroup();
+		item.setOwnerGroup(ownerGroup);
 		dbInstance.getCurrentEntityManager().persist(item);
 		if(owner != null) {
-			securityManager.addIdentityToSecurityGroup(owner, authorGroup);
+			securityManager.addIdentityToSecurityGroup(owner, ownerGroup);
 		}
 		return item;
 	}
@@ -110,10 +110,9 @@ public class QuestionItemDAO {
 		return sb.toString();
 	}
 	
-	
 	public void addAuthors(List<Identity> authors, QuestionItem item) {
 		QuestionItemImpl lockedItem = loadForUpdate(item.getKey());
-		SecurityGroup secGroup = lockedItem.getAuthorGroup();
+		SecurityGroup secGroup = lockedItem.getOwnerGroup();
 		for(Identity author:authors) {
 			if(!securityManager.isIdentityInSecurityGroup(author, secGroup)) {
 				securityManager.addIdentityToSecurityGroup(author, secGroup);
@@ -125,10 +124,10 @@ public class QuestionItemDAO {
 	public int countItems(Identity me) {
 		StringBuilder sb = new StringBuilder();
 		sb.append("select count(item) from questionitem item")
-		  .append(" inner join item.authorGroup authorGroup ")
-		  .append(" where authorGroup in (")
+		  .append(" inner join item.ownerGroup ownerGroup ")
+		  .append(" where ownerGroup in (")
 		  .append("   select vmember.securityGroup from ").append(SecurityGroupMembershipImpl.class.getName()).append(" as vmember ")
-		  .append("     where vmember.identity.key=:identityKey and vmember.securityGroup=authorGroup")
+		  .append("     where vmember.identity.key=:identityKey and vmember.securityGroup=ownerGroup")
 		  .append(" )");
 		return dbInstance.getCurrentEntityManager()
 				.createQuery(sb.toString(), Number.class)
@@ -139,10 +138,10 @@ public class QuestionItemDAO {
 	public List<QuestionItem> getItems(Identity me, int firstResult, int maxResults, SortKey... orderBy) {
 		StringBuilder sb = new StringBuilder();
 		sb.append("select item from questionitem item")
-		  .append(" inner join item.authorGroup authorGroup ")
-		  .append(" where authorGroup in (")
+		  .append(" inner join item.ownerGroup ownerGroup ")
+		  .append(" where ownerGroup in (")
 		  .append("   select vmember.securityGroup from ").append(SecurityGroupMembershipImpl.class.getName()).append(" as vmember ")
-		  .append("     where vmember.identity.key=:identityKey and vmember.securityGroup=authorGroup")
+		  .append("     where vmember.identity.key=:identityKey and vmember.securityGroup=ownerGroup")
 		  .append(" )");
 
 		TypedQuery<QuestionItem> query = dbInstance.getCurrentEntityManager()
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 aea658ec407..2bca0b4dd32 100644
--- a/src/main/java/org/olat/modules/qpool/manager/QuestionPoolServiceImpl.java
+++ b/src/main/java/org/olat/modules/qpool/manager/QuestionPoolServiceImpl.java
@@ -30,6 +30,7 @@ import java.util.List;
 import java.util.UUID;
 
 import org.apache.commons.io.IOUtils;
+import org.olat.basesecurity.BaseSecurity;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.commons.persistence.SortKey;
 import org.olat.core.id.Identity;
@@ -46,6 +47,8 @@ import org.olat.modules.qpool.QuestionItemCollection;
 import org.olat.modules.qpool.QuestionPoolModule;
 import org.olat.modules.qpool.QuestionPoolSPI;
 import org.olat.modules.qpool.QuestionPoolService;
+import org.olat.modules.qpool.StudyField;
+import org.olat.modules.qpool.model.PoolImpl;
 import org.olat.modules.qpool.model.QuestionItemImpl;
 import org.olat.resource.OLATResource;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -74,6 +77,8 @@ public class QuestionPoolServiceImpl implements QuestionPoolService {
 	private QuestionItemDAO questionItemDao;
 	@Autowired
 	private QuestionPoolModule qpoolModule;
+	@Autowired
+	private BaseSecurity securityManager;
 	
 
 	@Override
@@ -90,6 +95,7 @@ public class QuestionPoolServiceImpl implements QuestionPoolService {
 		
 		poolDao.deleteFromPools(items);
 		questionItemDao.deleteFromShares(items);
+		collectionDao.deleteItemFromCollections(items);
 		//TODO unmark
 		questionItemDao.delete(items);
 	}
@@ -229,7 +235,7 @@ public class QuestionPoolServiceImpl implements QuestionPoolService {
 
 	@Override
 	public List<Pool> getPools(Identity identity) {
-		return poolDao.getPools();
+		return poolDao.getPools(0, -1);
 	}
 
 	@Override
@@ -318,4 +324,39 @@ public class QuestionPoolServiceImpl implements QuestionPoolService {
 			int maxResults, SortKey... orderBy) {
 		return collectionDao.getItemsOfCollection(collection, firstResult, maxResults, orderBy);
 	}
+
+	@Override
+	public void createPool(Identity identity, String name) {
+		PoolImpl pool = poolDao.createPool(name);
+		securityManager.addIdentityToSecurityGroup(identity, pool.getOwnerGroup());
+	}
+
+	@Override
+	public Pool updatePool(Pool pool) {
+		return poolDao.updatePool(pool);
+	}
+
+	@Override
+	public void deletePool(Pool pool) {
+		poolDao.deletePool(pool);
+	}
+
+	@Override
+	public int countPools() {
+		return poolDao.countPools();
+	}
+
+	@Override
+	public List<Pool> getPools(int firstResult, int maxResults, SortKey... orderBy) {
+		return poolDao.getPools(firstResult, maxResults);
+	}
+
+	@Override
+	public List<StudyField> getStudyFields() {
+		return studyFieldDao.loadAllFields();
+	}
+	
+	
+	
+	
 }
diff --git a/src/main/java/org/olat/modules/qpool/manager/StudyFieldDAO.java b/src/main/java/org/olat/modules/qpool/manager/StudyFieldDAO.java
index 160ce247c7b..51b55392caa 100644
--- a/src/main/java/org/olat/modules/qpool/manager/StudyFieldDAO.java
+++ b/src/main/java/org/olat/modules/qpool/manager/StudyFieldDAO.java
@@ -73,7 +73,8 @@ public class StudyFieldDAO {
 	
 	public List<StudyField> loadAllFields() {
 		StringBuilder sb = new StringBuilder();
-		sb.append("select f from qstudyfield f ");
+		sb.append("select f from qstudyfield f ")
+		  .append(" left join fetch f.parentField pf");
 		return dbInstance.getCurrentEntityManager()
 				.createQuery(sb.toString(), StudyField.class)
 				.getResultList();
diff --git a/src/main/java/org/olat/modules/qpool/model/CollectionToItem.java b/src/main/java/org/olat/modules/qpool/model/CollectionToItem.java
index a48951cb3f9..065069028c9 100644
--- a/src/main/java/org/olat/modules/qpool/model/CollectionToItem.java
+++ b/src/main/java/org/olat/modules/qpool/model/CollectionToItem.java
@@ -35,7 +35,6 @@ import javax.persistence.TemporalType;
 import org.hibernate.annotations.GenericGenerator;
 import org.olat.core.id.CreateInfo;
 import org.olat.core.id.Persistable;
-import org.olat.modules.qpool.QuestionItem;
 import org.olat.modules.qpool.QuestionItemCollection;
 
 /**
@@ -66,7 +65,7 @@ public class CollectionToItem implements CreateInfo, Persistable  {
 	
 	@ManyToOne(targetEntity=QuestionItemImpl.class,fetch=FetchType.LAZY,optional=false)
 	@JoinColumn(name="fk_item_id", nullable=false, updatable=false)
-	private QuestionItem item;
+	private QuestionItemImpl item;
 
 	@Override
 	public Long getKey() {
@@ -94,11 +93,11 @@ public class CollectionToItem implements CreateInfo, Persistable  {
 		this.collection = collection;
 	}
 
-	public QuestionItem getItem() {
+	public QuestionItemImpl getItem() {
 		return item;
 	}
 
-	public void setItem(QuestionItem item) {
+	public void setItem(QuestionItemImpl item) {
 		this.item = item;
 	}
 
diff --git a/src/main/java/org/olat/modules/qpool/model/PoolImpl.java b/src/main/java/org/olat/modules/qpool/model/PoolImpl.java
index b9edbd99256..cff85f5ef66 100644
--- a/src/main/java/org/olat/modules/qpool/model/PoolImpl.java
+++ b/src/main/java/org/olat/modules/qpool/model/PoolImpl.java
@@ -23,8 +23,11 @@ import java.util.Date;
 
 import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.FetchType;
 import javax.persistence.GeneratedValue;
 import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
 import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
 import javax.persistence.Table;
@@ -32,6 +35,8 @@ import javax.persistence.Temporal;
 import javax.persistence.TemporalType;
 
 import org.hibernate.annotations.GenericGenerator;
+import org.olat.basesecurity.SecurityGroup;
+import org.olat.basesecurity.SecurityGroupImpl;
 import org.olat.core.id.CreateInfo;
 import org.olat.core.id.ModifiedInfo;
 import org.olat.core.id.Persistable;
@@ -69,6 +74,13 @@ public class PoolImpl implements Pool, CreateInfo, ModifiedInfo, Persistable {
 	@Column(name="q_name", nullable=false, insertable=true, updatable=true)
 	private String name;
 	
+	@ManyToOne(targetEntity=SecurityGroupImpl.class,fetch=FetchType.LAZY,optional=false)
+	@JoinColumn(name="fk_ownergroup", nullable=false, insertable=true, updatable=false)
+	private SecurityGroup ownerGroup;
+	@ManyToOne(targetEntity=SecurityGroupImpl.class,fetch=FetchType.LAZY,optional=false)
+	@JoinColumn(name="fk_participantgroup", nullable=false, insertable=true, updatable=false)
+	private SecurityGroup participantGroup;
+	
 	
 	public Long getKey() {
 		return key;
@@ -102,6 +114,22 @@ public class PoolImpl implements Pool, CreateInfo, ModifiedInfo, Persistable {
 		this.name = name;
 	}
 
+	public SecurityGroup getOwnerGroup() {
+		return ownerGroup;
+	}
+
+	public void setOwnerGroup(SecurityGroup ownerGroup) {
+		this.ownerGroup = ownerGroup;
+	}
+
+	public SecurityGroup getParticipantGroup() {
+		return participantGroup;
+	}
+
+	public void setParticipantGroup(SecurityGroup participantGroup) {
+		this.participantGroup = participantGroup;
+	}
+
 	@Override
 	public int hashCode() {
 		return key == null ? 19456 : key.hashCode();
diff --git a/src/main/java/org/olat/modules/qpool/model/QuestionItemImpl.java b/src/main/java/org/olat/modules/qpool/model/QuestionItemImpl.java
index af13a894d17..c1b7735b03b 100644
--- a/src/main/java/org/olat/modules/qpool/model/QuestionItemImpl.java
+++ b/src/main/java/org/olat/modules/qpool/model/QuestionItemImpl.java
@@ -91,8 +91,8 @@ public class QuestionItemImpl implements QuestionItem, CreateInfo, ModifiedInfo,
 	@Column(name="q_copyright", nullable=true, insertable=true, updatable=true)
 	private String copyright;
 	@ManyToOne(targetEntity=SecurityGroupImpl.class,fetch=FetchType.LAZY,optional=false)
-	@JoinColumn(name="fk_author_grp_id", nullable=false, insertable=true, updatable=false)
-	private SecurityGroup authorGroup;
+	@JoinColumn(name="fk_ownergroup", nullable=false, insertable=true, updatable=false)
+	private SecurityGroup ownerGroup;
 	
 	//usage
 	@Column(name="q_point", nullable=true, insertable=true, updatable=true)
@@ -137,7 +137,6 @@ public class QuestionItemImpl implements QuestionItem, CreateInfo, ModifiedInfo,
 		this.key = key;
 	}
 
-	@Override
 	public String getUuid() {
 		return uuid;
 	}
@@ -146,17 +145,14 @@ public class QuestionItemImpl implements QuestionItem, CreateInfo, ModifiedInfo,
 		this.uuid = uuid;
 	}
 
-	@Override
 	public String getResourceableTypeName() {
 		return "QuestionItem";
 	}
 
-	@Override
 	public Long getResourceableId() {
 		return getKey();
 	}
 
-	@Override
 	public Date getCreationDate() {
 		return creationDate;
 	}
@@ -262,7 +258,6 @@ public class QuestionItemImpl implements QuestionItem, CreateInfo, ModifiedInfo,
 		this.selectivity = selectivity;
 	}
 
-	@Override
 	@Transient
 	public QuestionStatus getQuestionStatus() {
 		if(StringHelper.containsNonWhitespace(status)) {
@@ -287,12 +282,12 @@ public class QuestionItemImpl implements QuestionItem, CreateInfo, ModifiedInfo,
 		this.copyright = copyright;
 	}
 
-	public SecurityGroup getAuthorGroup() {
-		return authorGroup;
+	public SecurityGroup getOwnerGroup() {
+		return ownerGroup;
 	}
 
-	public void setAuthorGroup(SecurityGroup authorGroup) {
-		this.authorGroup = authorGroup;
+	public void setOwnerGroup(SecurityGroup ownerGroup) {
+		this.ownerGroup = ownerGroup;
 	}
 
 	public BigDecimal getDifficulty() {
diff --git a/src/main/java/org/olat/modules/qpool/ui/CreateCollectionController.java b/src/main/java/org/olat/modules/qpool/ui/CreateCollectionController.java
index 167cccc2223..c121bbcc1d8 100644
--- a/src/main/java/org/olat/modules/qpool/ui/CreateCollectionController.java
+++ b/src/main/java/org/olat/modules/qpool/ui/CreateCollectionController.java
@@ -83,7 +83,7 @@ public class CreateCollectionController extends FormBasicController {
 		String name = nameEl.getValue();
 		nameEl.clearError();
 		if(!StringHelper.containsNonWhitespace(name)) {
-			nameEl.setErrorKey("", null);
+			nameEl.setErrorKey("form.mandatory.hover", null);
 		}
 		
 		return allOk && super.validateFormLogic(ureq);
diff --git a/src/main/java/org/olat/modules/qpool/ui/FilePreviewController.java b/src/main/java/org/olat/modules/qpool/ui/FilePreviewController.java
new file mode 100644
index 00000000000..4639bbd3691
--- /dev/null
+++ b/src/main/java/org/olat/modules/qpool/ui/FilePreviewController.java
@@ -0,0 +1,65 @@
+/**
+ * <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.qpool.ui;
+
+import org.olat.core.CoreSpringFactory;
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.Component;
+import org.olat.core.gui.components.velocity.VelocityContainer;
+import org.olat.core.gui.control.Event;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.gui.control.controller.BasicController;
+import org.olat.core.util.vfs.VFSLeaf;
+import org.olat.modules.qpool.QuestionItem;
+import org.olat.modules.qpool.QuestionPoolService;
+
+/**
+ * 
+ * Initial date: 27.02.2013<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class FilePreviewController extends BasicController {
+
+	private final VelocityContainer mainVC;
+	
+	public FilePreviewController(UserRequest ureq, WindowControl wControl, QuestionItem qitem) {
+		super(ureq, wControl);
+		QuestionPoolService qpoolService = CoreSpringFactory.getImpl(QuestionPoolService.class);
+		mainVC = createVelocityContainer("file_preview");
+		
+		VFSLeaf leaf = qpoolService.getRootFile(qitem);
+		if(leaf != null) {
+			mainVC.contextPut("filename", leaf.getName());
+		}
+		
+		putInitialPanel(mainVC);
+	}
+
+	@Override
+	protected void doDispose() {
+		//
+	}
+
+	@Override
+	protected void event(UserRequest ureq, Component source, Event event) {
+		//
+	}
+}
diff --git a/src/main/java/org/olat/modules/qpool/ui/PoolDataModel.java b/src/main/java/org/olat/modules/qpool/ui/PoolDataModel.java
new file mode 100644
index 00000000000..53687914abc
--- /dev/null
+++ b/src/main/java/org/olat/modules/qpool/ui/PoolDataModel.java
@@ -0,0 +1,130 @@
+/**
+ * <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.qpool.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.olat.core.commons.persistence.SortKey;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModel;
+import org.olat.core.gui.components.table.TableDataModel;
+import org.olat.core.gui.translator.Translator;
+import org.olat.modules.qpool.ui.PoolsAdminController.PoolSource;
+
+/**
+ * 
+ * Initial date: 23.01.2013<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class PoolDataModel implements FlexiTableDataModel, TableDataModel<PoolRow> {
+
+	private List<PoolRow> rows;
+	private PoolSource source;
+	private FlexiTableColumnModel columnModel;
+	private final Translator translator;
+	
+	public PoolDataModel(FlexiTableColumnModel columnModel, PoolSource source, Translator translator) {
+		this.columnModel = columnModel;
+		this.translator = translator;
+		this.source = source;
+	}
+	
+	@Override
+	public FlexiTableColumnModel getTableColumnModel() {
+		return columnModel;
+	}
+
+	@Override
+	public void setTableColumnModel(FlexiTableColumnModel tableColumnModel) {
+		this.columnModel = tableColumnModel;
+	}
+
+	@Override
+	public int getRowCount() {
+		return source.getNumOfItems();
+	}
+
+	@Override
+	public PoolRow getObject(int row) {
+		return rows.get(row);
+	}
+
+	@Override
+	public void setObjects(List<PoolRow> objects) {
+		rows = new ArrayList<PoolRow>(objects);
+	}
+
+	@Override
+	public void load(int firstResult, int maxResults, SortKey... orderBy) {
+		if(rows == null) {
+			rows = new ArrayList<PoolRow>();
+		}
+		
+		for(int i=rows.size(); i<firstResult; i++) {
+			rows.add(null);
+		}
+		List<PoolRow> newRows = source.getRows(firstResult, maxResults, orderBy);
+		for(int i=0; i<newRows.size(); i++) {
+			int rowIndex = i + firstResult;
+			if(rowIndex < rows.size()) {
+				rows.set(rowIndex, newRows.get(i));
+			} else {
+				rows.add(newRows.get(i));
+			}
+		}
+	}
+
+	@Override
+	public int getColumnCount() {
+		return columnModel.getColumnCount();
+	}
+	
+	@Override
+	public PoolDataModel createCopyWithEmptyList() {
+		return new PoolDataModel(columnModel, source, translator);
+	}
+
+	@Override
+	public Object getValueAt(int row, int col) {
+		PoolRow item = getObject(row);
+		switch(Cols.values()[col]) {
+			case id: return item.getKey();
+			case name: return item.getName();
+			default: return "";
+		}
+	}
+	
+	public enum Cols {
+		id("pool.key"),
+		name("pool.name");
+		
+		private final String i18nKey;
+	
+		private Cols(String i18nKey) {
+			this.i18nKey = i18nKey;
+		}
+		
+		public String i18nKey() {
+			return i18nKey;
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/qpool/ui/PoolEditController.java b/src/main/java/org/olat/modules/qpool/ui/PoolEditController.java
new file mode 100644
index 00000000000..2f9573695b2
--- /dev/null
+++ b/src/main/java/org/olat/modules/qpool/ui/PoolEditController.java
@@ -0,0 +1,97 @@
+/**
+ * <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.qpool.ui;
+
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.form.flexible.FormItemContainer;
+import org.olat.core.gui.components.form.flexible.elements.TextElement;
+import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
+import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
+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.util.StringHelper;
+import org.olat.modules.qpool.Pool;
+
+/**
+ * 
+ * Initial date: 21.02.2013<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class PoolEditController extends FormBasicController {
+
+	private TextElement nameEl;
+	private final Pool pool;
+	
+	public PoolEditController(UserRequest ureq, WindowControl wControl, Pool pool) {
+		super(ureq, wControl);
+		this.pool = pool;
+		initForm(ureq);
+	}
+	
+	public Pool getPool() {
+		return pool;
+	}
+	
+	public String getName() {
+		return nameEl.getValue();
+	}
+	
+	@Override
+	protected void doDispose() {
+		//
+	}
+
+	@Override
+	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		String name = pool == null ? "" : pool.getName();
+		nameEl = uifactory.addTextElement("pool.name", "pool.name", 128, name, formLayout);
+		
+		FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator());
+		buttonsCont.setRootForm(mainForm);
+		formLayout.add(buttonsCont);
+		uifactory.addFormSubmitButton("ok", "ok", buttonsCont);
+		uifactory.addFormCancelButton("cancel", buttonsCont, ureq, getWindowControl());
+	}
+
+	@Override
+	protected boolean validateFormLogic(UserRequest ureq) {
+		boolean allOk = true;
+
+		nameEl.clearError();
+		if(!StringHelper.containsNonWhitespace(nameEl.getValue())) {
+			nameEl.setErrorKey("form.mandatory.hover", null);
+			allOk = false;
+		}
+
+		return allOk && super.validateFormLogic(ureq);
+	}
+
+	@Override
+	protected void formOK(UserRequest ureq) {
+		fireEvent(ureq, Event.DONE_EVENT);
+	}
+
+	@Override
+	protected void formCancelled(UserRequest ureq) {
+		fireEvent(ureq, Event.CANCELLED_EVENT);
+	}
+}
diff --git a/src/main/java/org/olat/modules/qpool/ui/PoolRow.java b/src/main/java/org/olat/modules/qpool/ui/PoolRow.java
new file mode 100644
index 00000000000..c77df18698a
--- /dev/null
+++ b/src/main/java/org/olat/modules/qpool/ui/PoolRow.java
@@ -0,0 +1,49 @@
+/**
+ * <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.qpool.ui;
+
+import org.olat.modules.qpool.Pool;
+
+/**
+ * 
+ * Initial date: 28.02.2013<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class PoolRow {
+	
+	private final Pool pool;
+	
+	public PoolRow(Pool pool) {
+		this.pool = pool;
+	}
+
+	public Long getKey() {
+		return pool.getKey();
+	}
+
+	public String getName() {
+		return pool.getName();
+	}
+	
+	public Pool getPool() {
+		return pool;
+	}
+}
diff --git a/src/main/java/org/olat/modules/qpool/ui/PoolsAdminController.java b/src/main/java/org/olat/modules/qpool/ui/PoolsAdminController.java
new file mode 100644
index 00000000000..4bc368e2327
--- /dev/null
+++ b/src/main/java/org/olat/modules/qpool/ui/PoolsAdminController.java
@@ -0,0 +1,207 @@
+/**
+ * <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.qpool.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.olat.core.CoreSpringFactory;
+import org.olat.core.commons.persistence.SortKey;
+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.FlexiTableElement;
+import org.olat.core.gui.components.form.flexible.elements.FormLink;
+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.elements.table.DefaultFlexiColumnModel;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableRendererType;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel;
+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.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.modules.qpool.Pool;
+import org.olat.modules.qpool.QuestionPoolService;
+import org.olat.modules.qpool.ui.PoolDataModel.Cols;
+
+/**
+ * 
+ * Initial date: 21.02.2013<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class PoolsAdminController extends FormBasicController {
+	
+	private FormLink createPool;
+	
+	private PoolDataModel model;
+	private FlexiTableElement poolTable;
+	private CloseableModalController cmc;
+	private PoolEditController poolEditCtrl;
+	private DialogBoxController confirmDeleteCtrl;
+	
+	private final QuestionPoolService qpoolService;
+	
+	public PoolsAdminController(UserRequest ureq, WindowControl wControl) {
+		super(ureq, wControl, "pools_admin");
+		qpoolService = CoreSpringFactory.getImpl(QuestionPoolService.class);
+		initForm(ureq);
+	}
+	
+	@Override
+	protected void doDispose() {
+		//
+	}
+
+	@Override
+	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		//add the table
+		FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel();
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.id.i18nKey(), Cols.id.ordinal(), true, "key"));
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.name.i18nKey(), Cols.name.ordinal(), true, "name"));
+		columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("edit", translate("edit"), "edit-pool"));
+		columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("delete", translate("delete"), "delete-pool"));
+
+		model = new PoolDataModel(columnsModel, new PoolSource(), getTranslator());
+		poolTable = uifactory.addTableElement(ureq, "pools", model, 20, getTranslator(), formLayout);
+		poolTable.setRendererType(FlexiTableRendererType.classic);
+		
+		createPool = uifactory.addFormLink("create.pool", formLayout, Link.BUTTON);
+	}
+
+	@Override
+	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
+		if(source == createPool) {
+			doEditPool(ureq, null);
+		} else if(source == poolTable) {
+			if(event instanceof SelectionEvent) {
+				SelectionEvent se = (SelectionEvent)event;
+				if("edit-pool".equals(se.getCommand())) {
+					PoolRow row = model.getObject(se.getIndex());
+					doEditPool(ureq, row.getPool());
+				} else if("delete-pool".equals(se.getCommand())) {
+					PoolRow row = model.getObject(se.getIndex());
+					doConfirmDelete(ureq, row.getPool());
+				}
+			}
+		}
+		super.formInnerEvent(ureq, source, event);
+	}
+
+	@Override
+	protected void event(UserRequest ureq, Controller source, Event event) {
+		if(source == poolEditCtrl) {
+			if(event == Event.DONE_EVENT) {
+				Pool pool = poolEditCtrl.getPool();
+				if(pool == null) {
+					doCreate(ureq, poolEditCtrl.getName());
+				} else {
+					doEdit(ureq, pool, poolEditCtrl.getName());
+				}
+			}
+			cmc.deactivate();
+			cleanUp();
+		} else if(source == confirmDeleteCtrl) {
+			if(DialogBoxUIFactory.isOkEvent(event) || DialogBoxUIFactory.isYesEvent(event)) {
+				Pool pool = (Pool)confirmDeleteCtrl.getUserObject();
+				doDelete(ureq, pool);
+			}
+		} else if(source == cmc) {
+			cleanUp();
+		}
+	}
+	
+	private void cleanUp() {
+		removeAsListenerAndDispose(poolEditCtrl);
+		removeAsListenerAndDispose(cmc);
+		poolEditCtrl = null;
+		cmc = null;
+	}
+
+	@Override
+	protected void formOK(UserRequest ureq) {
+		//
+	}
+	
+	private void doConfirmDelete(UserRequest ureq, Pool pool) {
+		String title = translate("delete.pool");
+		String text = translate("delete.pool.confirm", new String[]{ pool.getName() });
+		confirmDeleteCtrl = activateOkCancelDialog(ureq, title, text, confirmDeleteCtrl);
+		confirmDeleteCtrl.setUserObject(pool);
+	}
+	
+	private void doDelete(UserRequest ureq, Pool pool) {
+		qpoolService.deletePool(pool);
+		poolTable.reset();
+		fireEvent(ureq, new QPoolEvent(QPoolEvent.POOL_DELETED));
+	}
+	
+	private void doEditPool(UserRequest ureq, Pool pool) {
+		removeAsListenerAndDispose(poolEditCtrl);
+		poolEditCtrl = new PoolEditController(ureq, getWindowControl(), pool);
+		listenTo(poolEditCtrl);
+		
+		cmc = new CloseableModalController(getWindowControl(), translate("close"),
+				poolEditCtrl.getInitialComponent(), true, translate("edit.pool"));
+		cmc.activate();
+		listenTo(cmc);	
+	}
+	
+	private void doCreate(UserRequest ureq, String name) {
+		qpoolService.createPool(getIdentity(), name);
+		poolTable.reset();
+		fireEvent(ureq, new QPoolEvent(QPoolEvent.POOL_CREATED));
+	}
+	
+	private void doEdit(UserRequest ureq, Pool pool, String name) {
+		pool.setName(name);
+		qpoolService.updatePool(pool);
+		poolTable.reset();
+		fireEvent(ureq, new QPoolEvent(QPoolEvent.POOL_CREATED));
+	}
+	
+	private PoolRow forgeRow(Pool pool) {
+		PoolRow row = new PoolRow(pool);
+		return row;
+	}
+	
+	public class PoolSource {
+
+		public int getNumOfItems() {
+			return qpoolService.countPools();
+		}
+
+		public List<PoolRow> getRows(int firstResult, int maxResults, SortKey... orderBy) {
+			List<Pool> pools = qpoolService.getPools(firstResult, maxResults, orderBy);
+			List<PoolRow> rows = new ArrayList<PoolRow>(pools.size());
+			for(Pool pool:pools) {
+				rows.add(forgeRow(pool));
+			}
+			return rows;
+		}
+	}
+}
diff --git a/src/main/java/org/olat/modules/qpool/ui/QPoolEvent.java b/src/main/java/org/olat/modules/qpool/ui/QPoolEvent.java
index 0145449f447..5210cb3e970 100644
--- a/src/main/java/org/olat/modules/qpool/ui/QPoolEvent.java
+++ b/src/main/java/org/olat/modules/qpool/ui/QPoolEvent.java
@@ -35,6 +35,8 @@ public class QPoolEvent extends MultiUserEvent {
 	public static final String ITEM_MARKED = "qpool-item-marked";
 	public static final String ITEM_DELETED = "qpool-item-deleted";
 	public static final String COLL_CREATED = "qpool-coll-created";
+	public static final String POOL_CREATED = "qpool-pool-created";
+	public static final String POOL_DELETED = "qpool-pool-deleted";
 	
 
 	public QPoolEvent(String cmd) {
diff --git a/src/main/java/org/olat/modules/qpool/ui/QuestionPoolMainEditorController.java b/src/main/java/org/olat/modules/qpool/ui/QuestionPoolMainEditorController.java
index 8ca712cdce2..4dd7623d3ef 100644
--- a/src/main/java/org/olat/modules/qpool/ui/QuestionPoolMainEditorController.java
+++ b/src/main/java/org/olat/modules/qpool/ui/QuestionPoolMainEditorController.java
@@ -57,7 +57,7 @@ import org.olat.modules.qpool.QuestionPoolService;
 public class QuestionPoolMainEditorController extends BasicController implements Activateable2, StackedControllerAware {
 
 	private final MenuTree menuTree;
-	private GenericTreeNode sharesNode, myNode;
+	private GenericTreeNode sharesNode, myNode, poolNode;
 	
 	private final Panel content;
 	private StackedController stackPanel;
@@ -68,6 +68,8 @@ public class QuestionPoolMainEditorController extends BasicController implements
 	private QuestionsController collItemsCtrl;
 	private QuestionsController selectedPoolCtrl;
 	private QuestionsController markedQuestionsCtrl;
+	
+	private PoolsAdminController poolAdminCtrl;
 	private StudyFieldAdminController studyFieldCtrl;
 	private LayoutMain3ColsController columnLayoutCtr;
 	private QuestionPoolAdminStatisticsController adminStatisticsCtrl;
@@ -123,6 +125,8 @@ public class QuestionPoolMainEditorController extends BasicController implements
 					doSelectAdmin(ureq);
 				} else if("menu.admin.studyfields".equals(uNode)) {
 					doSelectAdminStudyFields(ureq);
+				} else if("menu.admin.pools".equals(uNode)) {
+					doSelectAdminPools(ureq);
 				} else if("menu.database.my".equals(uNode)) {
 					doSelectMyQuestions(ureq);
 				} else if("menu.database.favorit".equals(uNode)) {
@@ -150,6 +154,10 @@ public class QuestionPoolMainEditorController extends BasicController implements
 			}	else if(QPoolEvent.COLL_CREATED.equals(event.getCommand())) {
 				buildMySubTreeModel(myNode);
 				menuTree.setDirty(true);
+			}	else if(QPoolEvent.POOL_CREATED.equals(event.getCommand())
+					|| QPoolEvent.POOL_DELETED.equals(event.getCommand())) {
+				buildPoolSubTreeModel(poolNode);
+				menuTree.setDirty(true);
 			}
 		}
 		super.event(ureq, source, event);
@@ -205,6 +213,14 @@ public class QuestionPoolMainEditorController extends BasicController implements
 		content.setContent(studyFieldCtrl.getInitialComponent());
 	}
 	
+	private void doSelectAdminPools(UserRequest ureq) {
+		if(poolAdminCtrl == null) {
+			poolAdminCtrl = new PoolsAdminController(ureq, getWindowControl());
+			listenTo(poolAdminCtrl);
+		}
+		content.setContent(poolAdminCtrl.getInitialComponent());
+	}
+	
 	private void doSelectMyQuestions(UserRequest ureq) {
 		if(myQuestionsCtrl == null) {
 			myQuestionsCtrl = new QuestionsController(ureq, getWindowControl(), new MyQuestionItemsSource(getIdentity()));
@@ -277,16 +293,11 @@ public class QuestionPoolMainEditorController extends BasicController implements
 
 
 		//pools
-		GenericTreeNode poolNode = new GenericTreeNode(translate("menu.pools"), "menu.pools.alt");
+		poolNode = new GenericTreeNode(translate("menu.pools"), "menu.pools.alt");
 		poolNode.setCssClass("o_sel_qpool_pools");
 		rootNode.addChild(poolNode);
 		
-		List<Pool> pools = qpoolService.getPools(getIdentity());
-		for(Pool pool:pools) {
-			GenericTreeNode node = new GenericTreeNode(pool.getName(), pool);
-			node.setIconCssClass("o_sel_qpool_pool");
-			poolNode.addChild(node);
-		}
+		buildPoolSubTreeModel(poolNode);
 		
 		//shares
 		sharesNode = new GenericTreeNode(translate("menu.share"), "menu.share");
@@ -298,12 +309,32 @@ public class QuestionPoolMainEditorController extends BasicController implements
 		GenericTreeNode adminNode = new GenericTreeNode(translate("menu.admin"), "menu.admin");
 		adminNode.setCssClass("o_sel_qpool_admin");
 		rootNode.addChild(adminNode);
+		buildAdminSubTreeModel(adminNode);
+
+		return gtm;
+	}
+	
+	private void buildPoolSubTreeModel(GenericTreeNode poolNode) {
+		poolNode.removeAllChildren();
+		
+		List<Pool> pools = qpoolService.getPools(getIdentity());
+		for(Pool pool:pools) {
+			GenericTreeNode node = new GenericTreeNode(pool.getName(), pool);
+			node.setIconCssClass("o_sel_qpool_pool");
+			poolNode.addChild(node);
+		}
+	}
+	
+	private void buildAdminSubTreeModel(GenericTreeNode adminNode) {
+		adminNode.removeAllChildren();
 		
 		GenericTreeNode node = new GenericTreeNode(translate("menu.admin.studyfields"), "menu.admin.studyfields");
 		node.setIconCssClass("o_sel_qpool_study_fields");
 		adminNode.addChild(node);
-
-		return gtm;
+		
+		node = new GenericTreeNode(translate("menu.admin.pools"), "menu.admin.pools");
+		node.setIconCssClass("o_sel_qpool_study_pools");
+		adminNode.addChild(node);
 	}
 	
 	private void buildMySubTreeModel(GenericTreeNode myNode) {
diff --git a/src/main/java/org/olat/modules/qpool/ui/StudyFieldAdminController.java b/src/main/java/org/olat/modules/qpool/ui/StudyFieldAdminController.java
index 18f84826d36..3abdc2b49fc 100644
--- a/src/main/java/org/olat/modules/qpool/ui/StudyFieldAdminController.java
+++ b/src/main/java/org/olat/modules/qpool/ui/StudyFieldAdminController.java
@@ -21,6 +21,7 @@ package org.olat.modules.qpool.ui;
 
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.Component;
+import org.olat.core.gui.components.tree.MenuTree;
 import org.olat.core.gui.components.velocity.VelocityContainer;
 import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
@@ -34,12 +35,26 @@ import org.olat.core.gui.control.controller.BasicController;
  */
 public class StudyFieldAdminController extends BasicController {
 
+	private final MenuTree studyFieldTree;
+	private final StudyFieldTreeModel studyFieldTreeModel;
+	
+	
 	private final VelocityContainer mainVC;
 	
 	public StudyFieldAdminController(UserRequest ureq, WindowControl wControl) {
 		super(ureq, wControl);
 		
 		mainVC = createVelocityContainer("admin_study_fields");
+
+		studyFieldTree = new MenuTree("qpoolTree");
+		studyFieldTreeModel = new StudyFieldTreeModel();
+		studyFieldTree.setTreeModel(studyFieldTreeModel);
+		studyFieldTree.setSelectedNode(studyFieldTree.getTreeModel().getRootNode());
+		studyFieldTree.setDropEnabled(false);
+		studyFieldTree.addListener(this);
+		studyFieldTree.setRootVisible(false);
+
+		mainVC.put("tree", studyFieldTree);
 		putInitialPanel(mainVC);
 	}
 	
diff --git a/src/main/java/org/olat/modules/qpool/ui/StudyFieldTreeModel.java b/src/main/java/org/olat/modules/qpool/ui/StudyFieldTreeModel.java
new file mode 100644
index 00000000000..00fc4993911
--- /dev/null
+++ b/src/main/java/org/olat/modules/qpool/ui/StudyFieldTreeModel.java
@@ -0,0 +1,78 @@
+/**
+ * <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.qpool.ui;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.olat.core.CoreSpringFactory;
+import org.olat.core.gui.components.tree.GenericTreeModel;
+import org.olat.core.gui.components.tree.GenericTreeNode;
+import org.olat.modules.qpool.QuestionPoolService;
+import org.olat.modules.qpool.StudyField;
+
+/**
+ * 
+ * Initial date: 28.02.2013<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class StudyFieldTreeModel extends GenericTreeModel {
+
+	private static final long serialVersionUID = 3032222581990406868L;
+	private QuestionPoolService qpoolService;
+	
+	public StudyFieldTreeModel() {
+		qpoolService = CoreSpringFactory.getImpl(QuestionPoolService.class);
+		
+		buildTree();
+	}
+	
+	private void buildTree() {
+		GenericTreeNode rootNode = new GenericTreeNode("root", "root");
+		setRootNode(rootNode);
+
+		List<StudyField> fields = qpoolService.getStudyFields();
+		Map<Long,GenericTreeNode> fieldKeyToNode = new HashMap<Long, GenericTreeNode>();
+		for(StudyField field:fields) {
+			Long key = field.getKey();
+			GenericTreeNode node = fieldKeyToNode.get(key);
+			if(node == null) {
+				node = new GenericTreeNode(field.getField(), field);
+				fieldKeyToNode.put(key, node);
+			}
+
+			StudyField parentField = field.getParentField();
+			if(parentField == null) {
+				//this is a root
+				rootNode.addChild(node);
+			} else {
+				Long parentKey = parentField.getKey();
+				GenericTreeNode parentNode = fieldKeyToNode.get(parentKey);
+				if(parentNode == null) {
+					parentNode = new GenericTreeNode(parentField.getField(), parentField);
+					fieldKeyToNode.put(key, parentNode);
+				}
+				parentNode.addChild(node);
+			}
+		}
+	}
+}
diff --git a/src/main/java/org/olat/modules/qpool/ui/TextPreviewController.java b/src/main/java/org/olat/modules/qpool/ui/TextPreviewController.java
new file mode 100644
index 00000000000..58588092554
--- /dev/null
+++ b/src/main/java/org/olat/modules/qpool/ui/TextPreviewController.java
@@ -0,0 +1,98 @@
+/**
+ * <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.qpool.ui;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringWriter;
+
+import org.apache.commons.io.IOUtils;
+import org.olat.core.CoreSpringFactory;
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.Component;
+import org.olat.core.gui.components.velocity.VelocityContainer;
+import org.olat.core.gui.control.Event;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.gui.control.controller.BasicController;
+import org.olat.core.util.vfs.VFSLeaf;
+import org.olat.modules.qpool.QuestionItem;
+import org.olat.modules.qpool.QuestionPoolService;
+
+/**
+ * 
+ * Initial date: 27.02.2013<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class TextPreviewController extends BasicController {
+
+	private final VelocityContainer mainVC;
+	private final QuestionPoolService qpoolService;
+	
+	public TextPreviewController(UserRequest ureq, WindowControl wControl, QuestionItem qitem) {
+		super(ureq, wControl);
+		qpoolService = CoreSpringFactory.getImpl(QuestionPoolService.class);
+		mainVC = createVelocityContainer("text_preview");
+		
+		VFSLeaf leaf = qpoolService.getRootFile(qitem);
+		if(leaf == null) {
+			//no data to preview
+		} else {
+			String txt = readSummary(leaf);
+			mainVC.contextPut("text", txt);
+		}
+		putInitialPanel(mainVC);
+	}
+
+	@Override
+	protected void doDispose() {
+		//
+	}
+	
+	protected String readSummary(VFSLeaf leaf) {
+    StringWriter out = new StringWriter();
+    InputStream in = leaf.getInputStream();
+    InputStreamReader inr = new InputStreamReader(in);
+		try {
+			char[] buffer = new char[4096];
+			
+			int count = 0;
+	    int n = 0;
+	    while (-1 != (n = inr.read(buffer))) {
+	        out.write(buffer, 0, n);
+	        count += n;
+	        if(count >= 10000) {
+	        	break;
+	        }
+	    }
+		} catch (Exception e) {
+			logError("", e);
+		} finally {
+			IOUtils.closeQuietly(inr);
+			IOUtils.closeQuietly(in);
+		}
+  	return out.toString();
+	}
+
+	@Override
+	protected void event(UserRequest ureq, Component source, Event event) {
+		//
+	}
+}
diff --git a/src/main/java/org/olat/modules/qpool/ui/_content/admin_study_fields.html b/src/main/java/org/olat/modules/qpool/ui/_content/admin_study_fields.html
index 06c9c2558fd..18c5abd0ca5 100644
--- a/src/main/java/org/olat/modules/qpool/ui/_content/admin_study_fields.html
+++ b/src/main/java/org/olat/modules/qpool/ui/_content/admin_study_fields.html
@@ -1,4 +1,6 @@
 <fieldset>
 	<legend>$r.translate("menu.admin.studyfields")</legend>
+	
+	$r.render("tree")
 
 </fieldset>
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/qpool/ui/_content/file_preview.html b/src/main/java/org/olat/modules/qpool/ui/_content/file_preview.html
new file mode 100644
index 00000000000..0a9ab81ff41
--- /dev/null
+++ b/src/main/java/org/olat/modules/qpool/ui/_content/file_preview.html
@@ -0,0 +1 @@
+$filename
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/qpool/ui/_content/pools_admin.html b/src/main/java/org/olat/modules/qpool/ui/_content/pools_admin.html
new file mode 100644
index 00000000000..8997df0ef41
--- /dev/null
+++ b/src/main/java/org/olat/modules/qpool/ui/_content/pools_admin.html
@@ -0,0 +1,14 @@
+<fieldset>
+	<legend>$r.translate("menu.admin.pools")</legend>
+	$r.render("pools")
+	<div class="b_clearfix o_qpool_button_bar_box">
+		<div class="o_qpool_button_bar">
+		$r.render("create.pool")
+		</div>
+	</div>
+</fieldset>
+
+
+
+
+
diff --git a/src/main/java/org/olat/modules/qpool/ui/_content/text_preview.html b/src/main/java/org/olat/modules/qpool/ui/_content/text_preview.html
new file mode 100644
index 00000000000..9427842596c
--- /dev/null
+++ b/src/main/java/org/olat/modules/qpool/ui/_content/text_preview.html
@@ -0,0 +1 @@
+$text
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_de.properties
index ae0b8e6fb11..b1dbd43b552 100644
--- a/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_de.properties
@@ -20,6 +20,7 @@ menu.pools=Pool
 menu.pools.alt=Pool
 menu.pools.main=Katalog
 menu.pools.main.alt=Katalog
+menu.admin.pools=Pools Verwaltung
 menu.share=Freigaben
 metadatas=Metadaten
 item.copyright=Copyright
@@ -46,6 +47,12 @@ item.shared=Frage {0} wurde freigegeben.
 item.pooled=Frage {0} wurde im Pool hinzugefügt.
 item.deleted=Frage wurde gelöscht.
 item.collectioned=Frage {0} wurde in der Liste hinzugefügt.
+pool.key=ID
+pool.name=Name
+create.pool=Pool erstellen
+delete.pool=Pool löschen
+delete.pool.confirm=Wollen Sie wirklich diesen Pool "{0}" löschen?
+edit.pool=Pool editieren
 inWork=In Bearbeitung
 inReview=In Review
 used=Verwendet
diff --git a/src/main/java/org/olat/search/SearchService.java b/src/main/java/org/olat/search/SearchService.java
index f6a24578eed..f1b279c9082 100644
--- a/src/main/java/org/olat/search/SearchService.java
+++ b/src/main/java/org/olat/search/SearchService.java
@@ -49,7 +49,9 @@ public interface SearchService {
    * @param doHighlighting Highlights founded text fragements in result  
    * @return               Search result for queury
    */
-	public SearchResults doSearch(String queryString, List<String> condQueries, Identity identity, Roles roles, int firstResult, int maxReturns, boolean doHighlighting) throws ServiceNotAvailableException, ParseException, QueryException;
+	public SearchResults doSearch(String queryString, List<String> condQueries, Identity identity, Roles roles,
+			int firstResult, int maxReturns, boolean doHighlighting)
+	throws ServiceNotAvailableException, ParseException, QueryException;
 	
 	/**
 	 * Check a query for similar words.
diff --git a/src/main/java/org/olat/search/service/SearchServiceImpl.java b/src/main/java/org/olat/search/service/SearchServiceImpl.java
index 63a85970c9b..cd8696af6ef 100644
--- a/src/main/java/org/olat/search/service/SearchServiceImpl.java
+++ b/src/main/java/org/olat/search/service/SearchServiceImpl.java
@@ -187,7 +187,9 @@ public class SearchServiceImpl implements SearchService {
  	 * @return              SearchResults object for this query
 	 */
 	@Override
-	public SearchResults doSearch(String queryString, List<String> condQueries, Identity identity, Roles roles, int firstResult, int maxResults, boolean doHighlighting) throws ServiceNotAvailableException, ParseException {
+	public SearchResults doSearch(String queryString, List<String> condQueries, Identity identity, Roles roles,
+			int firstResult, int maxResults, boolean doHighlighting)
+	throws ServiceNotAvailableException, ParseException {
 		try {
 			if (!existIndex()) {
 				log.warn("Index does not exist, can't search for queryString: "+queryString);
@@ -213,7 +215,6 @@ public class SearchServiceImpl implements SearchService {
 			  	query.add(condQuery, Occur.MUST);
 				}
 			}
-
 			if (log.isDebug()) log.debug("query=" + query);
 
 	    long startTime = System.currentTimeMillis();
diff --git a/src/main/java/org/olat/search/service/indexer/QuestionItemIndexer.java b/src/main/java/org/olat/search/service/indexer/QuestionItemIndexer.java
index 4150f38d5e5..f1a80bcffe7 100644
--- a/src/main/java/org/olat/search/service/indexer/QuestionItemIndexer.java
+++ b/src/main/java/org/olat/search/service/indexer/QuestionItemIndexer.java
@@ -1,3 +1,22 @@
+/**
+ * <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.search.service.indexer;
 
 import java.io.IOException;
diff --git a/src/main/resources/database/mysql/alter_8_4_0_to_9_0_0.sql b/src/main/resources/database/mysql/alter_8_4_0_to_9_0_0.sql
index 308df5e13cb..a56993ae711 100644
--- a/src/main/resources/database/mysql/alter_8_4_0_to_9_0_0.sql
+++ b/src/main/resources/database/mysql/alter_8_4_0_to_9_0_0.sql
@@ -12,6 +12,8 @@ create table if not exists o_qp_pool (
    creationdate datetime not null,
    lastmodified datetime not null,
    q_name varchar(255) not null,
+   fk_ownergroup bigint,
+   fk_participantgroup bigint,
    primary key (id)
 );
 
@@ -48,7 +50,7 @@ create table if not exists o_qp_item (
    q_dir varchar(32),
    q_root_filename varchar(255),
    fk_study_field bigint,
-   fk_author_grp_id bigint,
+   fk_ownergroup bigint,
    primary key (id)
 );
 
@@ -85,6 +87,10 @@ create table if not exists o_qp_collection_2_item (
    primary key (id)
 );
 
+
+alter table o_qp_pool add constraint idx_qp_pool_owner_grp_id foreign key (fk_ownergroup) references o_bs_secgroup(id);
+alter table o_qp_pool add constraint idx_qp_pool_part_grp_id foreign key (fk_participantgroup) references o_bs_secgroup(id);
+
 alter table o_qp_pool_2_item add constraint idx_qp_pool_2_item_pool_id foreign key (fk_pool_id) references o_qp_pool(id);
 alter table o_qp_pool_2_item add constraint idx_qp_pool_2_item_item_id foreign key (fk_item_id) references o_qp_item(id);
 alter table o_qp_pool_2_item add unique (fk_pool_id, fk_item_id);
@@ -100,7 +106,7 @@ alter table o_qp_collection_2_item add constraint idx_qp_coll_item_id foreign ke
 alter table o_qp_collection_2_item add unique (fk_collection_id, fk_item_id);
 
 alter table o_qp_item add constraint idx_qp_pool_2_field_id foreign key (fk_study_field) references o_qp_study_field(id);
-alter table o_qp_item add constraint idx_qp_item_author_grp_id foreign key (fk_author_grp_id) references o_bs_secgroup(id);
+alter table o_qp_item add constraint idx_qp_item_owner_id foreign key (fk_ownergroup) references o_bs_secgroup(id);
 alter table o_qp_study_field add constraint idx_qp_field_2_parent_id foreign key (fk_parent_field) references o_qp_study_field(id);
 
 
diff --git a/src/test/java/org/olat/modules/ims/qti/fileresource/FileResourceValidatorTest.java b/src/test/java/org/olat/modules/ims/qti/fileresource/FileResourceValidatorTest.java
index c28b7e1eb55..9e2585c8dca 100644
--- a/src/test/java/org/olat/modules/ims/qti/fileresource/FileResourceValidatorTest.java
+++ b/src/test/java/org/olat/modules/ims/qti/fileresource/FileResourceValidatorTest.java
@@ -1,3 +1,22 @@
+/**
+ * <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.ims.qti.fileresource;
 
 import static org.junit.Assert.assertNotNull;
diff --git a/src/test/java/org/olat/modules/qpool/manager/PoolDAOTest.java b/src/test/java/org/olat/modules/qpool/manager/PoolDAOTest.java
index 72f243c78ab..210f92d2e34 100644
--- a/src/test/java/org/olat/modules/qpool/manager/PoolDAOTest.java
+++ b/src/test/java/org/olat/modules/qpool/manager/PoolDAOTest.java
@@ -70,7 +70,7 @@ public class PoolDAOTest extends OlatTestCase {
 		dbInstance.commitAndCloseSession();
 		
 		//get pools
-		List<Pool> pools = poolDao.getPools();
+		List<Pool> pools = poolDao.getPools(0, -1);
 		Assert.assertNotNull(pools);
 		Assert.assertTrue(pools.size() >= 1);
 		int numOfPools = poolDao.getNumOfPools();
-- 
GitLab