From 9d963fc1a264a9d9f768538f705ea12f50eff114 Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Fri, 5 Jan 2018 19:48:36 +0100
Subject: [PATCH] OO-3231: implements a dedicated indexer for the templates of
 the document pool

---
 .../_i18n/LocalStrings_de.properties          |  1 +
 .../_i18n/LocalStrings_en.properties          |  1 +
 .../search/indexer/DocumentPoolIndexer.java   | 24 ++++-
 .../ui/DocumentDirectoryController.java       | 11 ++-
 .../ui/DocumentPoolMainController.java        | 33 +++++--
 .../indexer/TaxonomyLibraryIndexer.java       | 19 ++--
 .../TaxonomyTemplatesLibraryIndexer.java      | 94 +++++++++++++++++++
 .../search/ui/SearchControllerFactory.java    |  3 +
 .../ui/_i18n/LocalStrings_de.properties       |  1 +
 .../ui/_i18n/LocalStrings_en.properties       |  1 +
 10 files changed, 159 insertions(+), 29 deletions(-)
 create mode 100644 src/main/java/org/olat/modules/taxonomy/search/indexer/TaxonomyTemplatesLibraryIndexer.java

diff --git a/src/main/java/org/olat/core/commons/chiefcontrollers/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/core/commons/chiefcontrollers/_i18n/LocalStrings_de.properties
index 896fa69f2bb..fbd5f9dcfe9 100644
--- a/src/main/java/org/olat/core/commons/chiefcontrollers/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/core/commons/chiefcontrollers/_i18n/LocalStrings_de.properties
@@ -47,6 +47,7 @@ PFCourseNode=Drop Box
 ReturnboxController=R\u00FCckgabeordner
 SolutionController=Musterl\u00F6sungen
 TaxonomyLibrary=Taxonomy Bibliothek
+Templates=Vorlage
 User=Benutzer
 WikiPage=Wiki
 ajax.show.on=[Ajax-Beta-Mode]
diff --git a/src/main/java/org/olat/core/commons/chiefcontrollers/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/core/commons/chiefcontrollers/_i18n/LocalStrings_en.properties
index 6423c844c34..a6d6b0f4d3f 100644
--- a/src/main/java/org/olat/core/commons/chiefcontrollers/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/core/commons/chiefcontrollers/_i18n/LocalStrings_en.properties
@@ -47,6 +47,7 @@ PFCourseNode=Drop Box
 ReturnboxController=Return box
 SolutionController=Sample solutions
 TaxonomyLibrary=Taxonomy library
+Templates=Templates
 User=User
 WikiPage=Wiki
 ajax.show.on=[Ajax-Beta-Mode]
diff --git a/src/main/java/org/olat/modules/docpool/search/indexer/DocumentPoolIndexer.java b/src/main/java/org/olat/modules/docpool/search/indexer/DocumentPoolIndexer.java
index c7280645db6..3d5bd5795bf 100644
--- a/src/main/java/org/olat/modules/docpool/search/indexer/DocumentPoolIndexer.java
+++ b/src/main/java/org/olat/modules/docpool/search/indexer/DocumentPoolIndexer.java
@@ -20,8 +20,13 @@
 package org.olat.modules.docpool.search.indexer;
 
 import java.io.IOException;
+import java.util.List;
 
+import org.olat.core.id.Identity;
 import org.olat.core.id.OLATResourceable;
+import org.olat.core.id.Roles;
+import org.olat.core.id.context.BusinessControl;
+import org.olat.core.id.context.ContextEntry;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.resource.OresHelper;
 import org.olat.modules.docpool.DocumentPoolModule;
@@ -45,11 +50,6 @@ public class DocumentPoolIndexer extends TaxonomyLibraryIndexer implements Initi
 	
 	@Autowired
 	private DocumentPoolModule documentPoolModule;
-	
-	@Override
-	public void afterPropertiesSet() throws Exception {
-		addIndexer(taxonomyLevelLibraryIndexer);
-	}
 
 	@Override
 	public String getSupportedTypeName() {
@@ -74,4 +74,18 @@ public class DocumentPoolIndexer extends TaxonomyLibraryIndexer implements Initi
 			doIndexTaxonomyLibrary(searchResourceContext, taxonomy, indexerWriter);
 		}
 	}
+
+	@Override
+	public boolean checkAccess(ContextEntry contextEntry, BusinessControl businessControl, Identity identity, Roles roles) {
+		if(!documentPoolModule.isTemplatesDirectoryEnabled()) {
+			//discard templates content
+			List<ContextEntry> entries = businessControl.getEntriesDownTheControls();
+			for(ContextEntry entry:entries) {
+				if("Templates".equals(entry.getOLATResourceable().getResourceableTypeName())) {
+					return false;
+				}
+			}
+		}
+		return super.checkAccess(contextEntry, businessControl, identity, roles);
+	}
 }
diff --git a/src/main/java/org/olat/modules/docpool/ui/DocumentDirectoryController.java b/src/main/java/org/olat/modules/docpool/ui/DocumentDirectoryController.java
index 40447637ba6..b1c4f39a82b 100644
--- a/src/main/java/org/olat/modules/docpool/ui/DocumentDirectoryController.java
+++ b/src/main/java/org/olat/modules/docpool/ui/DocumentDirectoryController.java
@@ -33,7 +33,6 @@ import org.olat.core.id.context.ContextEntry;
 import org.olat.core.id.context.StateEntry;
 import org.olat.core.util.vfs.NamedContainerImpl;
 import org.olat.core.util.vfs.VFSContainer;
-import org.olat.modules.taxonomy.Taxonomy;
 
 /**
  * 
@@ -45,12 +44,11 @@ public class DocumentDirectoryController extends BasicController implements Acti
 	
 	private final VelocityContainer mainVC;
 	private FolderRunController folderCtrl;
-
 	
 	public DocumentDirectoryController(UserRequest ureq, WindowControl wControl,
-			Taxonomy taxonomy, VFSContainer documents, String name) {
+			VFSContainer documents, String name) {
 		super(ureq, wControl);
-
+		
 		mainVC = createVelocityContainer("document_directory");
 		mainVC.contextPut("iconCssClass", "o_icon_taxonomy_templates");
 		mainVC.contextPut("displayName", name);
@@ -58,11 +56,14 @@ public class DocumentDirectoryController extends BasicController implements Acti
 		String rootName = translate("document.pool.templates");
 		VFSContainer namedContainer = new NamedContainerImpl(rootName, documents);
 		folderCtrl = new FolderRunController(namedContainer, true, true, true, ureq, getWindowControl());
-		folderCtrl.setResourceURL("[DocumentPool:" + taxonomy.getKey() + "]");
 		mainVC.put("folder", folderCtrl.getInitialComponent());
 
 		putInitialPanel(mainVC);
 	}
+	
+	public void setAdditionalResourceURL(String additionalUrl) {
+		folderCtrl.setResourceURL("[DocumentPool:0]" + additionalUrl);
+	}
 
 	@Override
 	protected void doDispose() {
diff --git a/src/main/java/org/olat/modules/docpool/ui/DocumentPoolMainController.java b/src/main/java/org/olat/modules/docpool/ui/DocumentPoolMainController.java
index ea49d38db3b..adc21d0e9a4 100644
--- a/src/main/java/org/olat/modules/docpool/ui/DocumentPoolMainController.java
+++ b/src/main/java/org/olat/modules/docpool/ui/DocumentPoolMainController.java
@@ -35,9 +35,11 @@ import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.controller.MainLayoutBasicController;
 import org.olat.core.gui.control.generic.dtabs.Activateable2;
+import org.olat.core.id.OLATResourceable;
 import org.olat.core.id.context.ContextEntry;
 import org.olat.core.id.context.StateEntry;
 import org.olat.core.util.StringHelper;
+import org.olat.core.util.resource.OresHelper;
 import org.olat.core.util.tree.TreeHelper;
 import org.olat.core.util.vfs.VFSContainer;
 import org.olat.core.util.vfs.callbacks.FullAccessCallback;
@@ -102,6 +104,7 @@ public class DocumentPoolMainController extends MainLayoutBasicController implem
 		content.setNeverDisposeRootController(true);
 		content.setToolbarAutoEnabled(true);
 		
+		
 		TreeNode root = taxonomyTree.getTreeModel().getRootNode();
 		if(root.getChildCount() > 0) {
 			taxonomyTree.open((TreeNode)root.getChildAt(0));
@@ -138,15 +141,16 @@ public class DocumentPoolMainController extends MainLayoutBasicController implem
 			}
 		} else {
 			String resourceName = entries.get(0).getOLATResourceable().getResourceableTypeName();
-			if(resourceName.startsWith("path=")) {
+			if("Templates".equals(resourceName) || resourceName.startsWith("path=")) {
 				TreeNode rootNode = taxonomyTree.getTreeModel().getRootNode();
 				if(rootNode.getChildCount() > 0) {
 					TaxonomyTreeNode node = (TaxonomyTreeNode)rootNode.getChildAt(0);
-					if(node.getType() == TaxonomyTreeNodeType.templates || node.getType() == TaxonomyTreeNodeType.lostAndFound) {
-						DocumentDirectoryController directoryCtrl = doSelectTaxonomyDirectory(ureq, node);
+					if(node.getType() == TaxonomyTreeNodeType.templates) {
+						DocumentDirectoryController directoryCtrl = doSelectTemplatesDirectory(ureq, node);
 						if(directoryCtrl != null) {
 							taxonomyTree.setSelectedNode(node);
-							directoryCtrl.activate(ureq, entries, null);
+							List<ContextEntry> subEntries = entries.subList(1, entries.size());
+							directoryCtrl.activate(ureq, subEntries, entries.get(0).getTransientState());
 						}
 					}
 				}
@@ -161,7 +165,7 @@ public class DocumentPoolMainController extends MainLayoutBasicController implem
 						levelCtrl.activate(ureq, subEntries, entries.get(0).getTransientState());
 					}
 				}
-			}
+			} 
 		}
 	}
 
@@ -195,6 +199,9 @@ public class DocumentPoolMainController extends MainLayoutBasicController implem
 					TaxonomyTreeNode node = (TaxonomyTreeNode)popEvent.getUserObject();
 					doSelect(ureq, node);
 					taxonomyTree.setSelectedNode(node);
+				} else if(popEvent.getController() instanceof DocumentDirectoryController) {
+					//pop the templates
+					taxonomyTree.setSelectedNode(taxonomyTree.getTreeModel().getRootNode());
 				}
 			}
 		}
@@ -206,12 +213,13 @@ public class DocumentPoolMainController extends MainLayoutBasicController implem
 				doSelectTaxonomy(ureq);
 				break;
 			case templates:
-			case lostAndFound:
-				doSelectTaxonomyDirectory(ureq, node);
+				doSelectTemplatesDirectory(ureq, node);
 				break;
 			case taxonomyLevel:
 				doSelectTaxonomyLevel(ureq, node);
 				break;
+			case lostAndFound:
+				break;
 		}
 	}
 	
@@ -219,7 +227,7 @@ public class DocumentPoolMainController extends MainLayoutBasicController implem
 		content.popUpToRootController(ureq);
 	}
 	
-	private DocumentDirectoryController doSelectTaxonomyDirectory(UserRequest ureq, TaxonomyTreeNode node) {
+	private DocumentDirectoryController doSelectTemplatesDirectory(UserRequest ureq, TaxonomyTreeNode node) {
 		content.popUpToRootController(ureq);
 		
 		VFSContainer directory = node.getDirectory();
@@ -227,7 +235,10 @@ public class DocumentPoolMainController extends MainLayoutBasicController implem
 		directory.setLocalSecurityCallback(secCallback);
 		
 		String name = translate("document.pool.templates");
-		DocumentDirectoryController directoryCtrl = new DocumentDirectoryController(ureq, getWindowControl(), node.getTaxonomy(), directory, name);
+		OLATResourceable ores = OresHelper.createOLATResourceableInstance("Templates", 0l);
+		WindowControl bwControl = addToHistory(ureq, ores, null);
+		DocumentDirectoryController directoryCtrl = new DocumentDirectoryController(ureq, bwControl, directory, name);
+		directoryCtrl.setAdditionalResourceURL("[Templates:0]");
 		listenTo(directoryCtrl);
 
 		content.pushController(name, directoryCtrl);
@@ -240,7 +251,9 @@ public class DocumentPoolMainController extends MainLayoutBasicController implem
 
 			SubscriptionContext subscriptionCtx = notificationsHandler.getTaxonomyDocumentsLibrarySubscriptionContext();
 			TaxonomyVFSSecurityCallback secCallback = new TaxonomyVFSSecurityCallback(node, subscriptionCtx);
-			DocumentPoolLevelController levelCtrl = new DocumentPoolLevelController(ureq, getWindowControl(), level, node, secCallback);
+			OLATResourceable ores = OresHelper.createOLATResourceableInstance("TaxonomyLevel", node.getTaxonomyLevel().getKey());
+			WindowControl bwControl = addToHistory(ureq, ores, null);
+			DocumentPoolLevelController levelCtrl = new DocumentPoolLevelController(ureq, bwControl, level, node, secCallback);
 			listenTo(levelCtrl);
 			String displayName = level.getDisplayName();
 			
diff --git a/src/main/java/org/olat/modules/taxonomy/search/indexer/TaxonomyLibraryIndexer.java b/src/main/java/org/olat/modules/taxonomy/search/indexer/TaxonomyLibraryIndexer.java
index fe2a63d8d04..e7003b1a10d 100644
--- a/src/main/java/org/olat/modules/taxonomy/search/indexer/TaxonomyLibraryIndexer.java
+++ b/src/main/java/org/olat/modules/taxonomy/search/indexer/TaxonomyLibraryIndexer.java
@@ -36,8 +36,6 @@ import org.olat.modules.taxonomy.TaxonomyService;
 import org.olat.modules.taxonomy.model.TaxonomyRefImpl;
 import org.olat.search.service.SearchResourceContext;
 import org.olat.search.service.indexer.AbstractHierarchicalIndexer;
-import org.olat.search.service.indexer.FolderIndexerAccess;
-import org.olat.search.service.indexer.FolderIndexerWorker;
 import org.olat.search.service.indexer.OlatFullIndexer;
 import org.springframework.beans.factory.InitializingBean;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -54,23 +52,26 @@ public abstract class TaxonomyLibraryIndexer extends AbstractHierarchicalIndexer
 	protected TaxonomyService taxonomyService;
 	@Autowired
 	protected TaxonomyLevelLibraryIndexer taxonomyLevelLibraryIndexer;
+	@Autowired
+	protected TaxonomyTemplatesLibraryIndexer taxonomyTemplatesLibraryIndexer;
 	
 	@Override
 	public void afterPropertiesSet() throws Exception {
 		addIndexer(taxonomyLevelLibraryIndexer);
+		addIndexer(taxonomyTemplatesLibraryIndexer);
 	}
 	
 	protected void doIndexTaxonomyLibrary(SearchResourceContext searchResourceContext, Taxonomy taxonomy, OlatFullIndexer indexerWriter)
 	throws InterruptedException  {
 		VFSContainer templatesContainer = taxonomyService.getDocumentsLibrary(taxonomy);
 		if(templatesContainer != null) {
-			FolderIndexerWorker runnableFolderIndexer = new  FolderIndexerWorker();
-			runnableFolderIndexer.setAccessRule(FolderIndexerAccess.FULL_ACCESS);
-			runnableFolderIndexer.setParentResourceContext(searchResourceContext);
-			runnableFolderIndexer.setContainer(templatesContainer);
-			runnableFolderIndexer.setIndexWriter(indexerWriter);
-			runnableFolderIndexer.setFilePath("");
-			indexerWriter.submit(runnableFolderIndexer);
+			try {
+				taxonomyTemplatesLibraryIndexer.doIndex(searchResourceContext, taxonomy, indexerWriter);
+			} catch(InterruptedException e) {
+				throw e;
+			} catch (Exception e) {
+				logError("", e);
+			}
 		}
 		
 		List<TaxonomyLevel> levels = taxonomyService.getTaxonomyLevels(taxonomy);
diff --git a/src/main/java/org/olat/modules/taxonomy/search/indexer/TaxonomyTemplatesLibraryIndexer.java b/src/main/java/org/olat/modules/taxonomy/search/indexer/TaxonomyTemplatesLibraryIndexer.java
new file mode 100644
index 00000000000..a94117ed783
--- /dev/null
+++ b/src/main/java/org/olat/modules/taxonomy/search/indexer/TaxonomyTemplatesLibraryIndexer.java
@@ -0,0 +1,94 @@
+/**
+ * <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.taxonomy.search.indexer;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.List;
+
+import org.olat.core.id.Identity;
+import org.olat.core.id.OLATResourceable;
+import org.olat.core.id.Roles;
+import org.olat.core.id.context.BusinessControl;
+import org.olat.core.id.context.ContextEntry;
+import org.olat.core.util.resource.OresHelper;
+import org.olat.core.util.vfs.VFSContainer;
+import org.olat.modules.taxonomy.Taxonomy;
+import org.olat.modules.taxonomy.TaxonomyCompetenceTypes;
+import org.olat.modules.taxonomy.TaxonomyRef;
+import org.olat.modules.taxonomy.TaxonomyService;
+import org.olat.modules.taxonomy.model.TaxonomyRefImpl;
+import org.olat.search.service.SearchResourceContext;
+import org.olat.search.service.indexer.DefaultIndexer;
+import org.olat.search.service.indexer.FolderIndexerAccess;
+import org.olat.search.service.indexer.FolderIndexerWorker;
+import org.olat.search.service.indexer.OlatFullIndexer;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 
+ * Initial date: 5 janv. 2018<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+@Service("taxonomyTemplatesLibraryIndexer")
+public class TaxonomyTemplatesLibraryIndexer extends DefaultIndexer {
+	
+	@Autowired
+	protected TaxonomyService taxonomyService;
+
+	@Override
+	public String getSupportedTypeName() {
+		return "Templates";
+	}
+	
+	@Override
+	public void doIndex(SearchResourceContext parentResourceContext, Object parentObject, OlatFullIndexer indexerWriter)
+	throws IOException, InterruptedException {
+		Taxonomy taxonomy = (Taxonomy)parentObject;
+		VFSContainer templatesContainer = taxonomyService.getDocumentsLibrary(taxonomy);
+		if(templatesContainer != null) {
+			SearchResourceContext searchResourceContext = new SearchResourceContext(parentResourceContext);
+			OLATResourceable templateOres = OresHelper.createOLATResourceableInstance(getSupportedTypeName(), 0l);
+			searchResourceContext.setBusinessControlFor(templateOres);
+
+			FolderIndexerWorker runnableFolderIndexer = new  FolderIndexerWorker();
+			runnableFolderIndexer.setAccessRule(FolderIndexerAccess.FULL_ACCESS);
+			runnableFolderIndexer.setParentResourceContext(searchResourceContext);
+			runnableFolderIndexer.setContainer(templatesContainer);
+			runnableFolderIndexer.setIndexWriter(indexerWriter);
+			runnableFolderIndexer.setFilePath("");
+			indexerWriter.submit(runnableFolderIndexer);
+		}
+	}
+
+	@Override
+	public boolean checkAccess(ContextEntry contextEntry, BusinessControl businessControl, Identity identity, Roles roles) {
+		if(roles.isOLATAdmin()) return true;
+		
+		List<ContextEntry> entries = businessControl.getEntriesDownTheControls();
+		if(entries.size() == 1) {
+			TaxonomyRef taxonomy = new TaxonomyRefImpl(contextEntry.getOLATResourceable().getResourceableId());
+			return taxonomyService.hasTaxonomyCompetences(taxonomy, identity, new Date(), TaxonomyCompetenceTypes.manage, TaxonomyCompetenceTypes.teach);
+		}
+		return false;
+	}
+}
diff --git a/src/main/java/org/olat/search/ui/SearchControllerFactory.java b/src/main/java/org/olat/search/ui/SearchControllerFactory.java
index 2d702bc06d2..0b299ee19ab 100644
--- a/src/main/java/org/olat/search/ui/SearchControllerFactory.java
+++ b/src/main/java/org/olat/search/ui/SearchControllerFactory.java
@@ -135,6 +135,9 @@ public class SearchControllerFactory implements SearchServiceUIFactory {
 				if ("DocumentPool".equals(tokenType)) {
 					return translator.translate("DocumentPool");
 				}
+				if ("Templates".equals(tokenType)) {
+					return translator.translate("Templates");
+				}
 				if("userfolder".equals(tokenType)) {
 					return translator.translate("type.identity.publicfolder");
 				}
diff --git a/src/main/java/org/olat/search/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/search/ui/_i18n/LocalStrings_de.properties
index 886c10f78d3..52db6f3f46d 100644
--- a/src/main/java/org/olat/search/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/search/ui/_i18n/LocalStrings_de.properties
@@ -103,6 +103,7 @@ LibrarySite=Bibliothek
 Taxonomy=Taxonomy
 DocumentPool=Dokumentenpool
 TaxonomyLevel=Taxonomy Level
+Templates=Vorlage
 type.file=Datei
 type.file.html=HTML-Datei
 type.file.word=Word-Datei
diff --git a/src/main/java/org/olat/search/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/search/ui/_i18n/LocalStrings_en.properties
index 58c7c0fb4c4..02b42716660 100644
--- a/src/main/java/org/olat/search/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/search/ui/_i18n/LocalStrings_en.properties
@@ -62,6 +62,7 @@ switch.advanced.search=Advanced search
 switch.simple.search=Simple search
 Taxonomy=Taxonomy
 TaxonomyLevel=Taxonomy Level
+Templates=Templates
 too.many.results=Too many results found. Only the first {0} will be displayed.
 toolfolder=Folder
 toolforum=Forums
-- 
GitLab