diff --git a/src/main/java/org/olat/_spring/mainContext.xml b/src/main/java/org/olat/_spring/mainContext.xml index 7407d055155c7f314f1f447980b85f2deb055bc4..1a40e3a4b93f709ca8af057624cc3b4363a6c9a9 100644 --- a/src/main/java/org/olat/_spring/mainContext.xml +++ b/src/main/java/org/olat/_spring/mainContext.xml @@ -9,7 +9,7 @@ http://www.springframework.org/schema/context/spring-context.xsd"> <context:property-placeholder location="classpath:serviceconfig/olat.properties, classpath:olat.local.properties" system-properties-mode="OVERRIDE"/> - <context:component-scan base-package="org.olat.basesecurity,org.olat.note,org.olat.social,org.olat.commons.memberlist,org.olat.commons.info" /> + <context:component-scan base-package="org.olat.basesecurity,org.olat.note,org.olat.social,org.olat.commons.memberlist,org.olat.commons.info,org.olat.collaboration" /> <context:annotation-config /> <import resource="classpath:/org/olat/core/_spring/mainCorecontext.xml"/> diff --git a/src/main/java/org/olat/admin/sysinfo/LargeFilesController.java b/src/main/java/org/olat/admin/sysinfo/LargeFilesController.java index 9ae57138866463935e8689e131dedada0c8ea2fa..388d345e32de53d794754f5cb57fe1f2cc8a6c5f 100644 --- a/src/main/java/org/olat/admin/sysinfo/LargeFilesController.java +++ b/src/main/java/org/olat/admin/sysinfo/LargeFilesController.java @@ -37,6 +37,7 @@ import org.olat.admin.sysinfo.model.LargeFilesTableModel; import org.olat.admin.sysinfo.model.LargeFilesTableModel.LargeFilesTableColumns; import org.olat.core.commons.persistence.SortKey; import org.olat.core.commons.services.taskexecutor.TaskExecutorManager; +import org.olat.core.commons.services.vfs.VFSContextInfo; import org.olat.core.commons.services.vfs.VFSFilterKeys; import org.olat.core.commons.services.vfs.VFSMetadata; import org.olat.core.commons.services.vfs.VFSRepositoryModule; @@ -60,8 +61,8 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.link.Link; -import org.olat.core.gui.components.text.TextFactory; import org.olat.core.gui.components.util.KeyValues; +import org.olat.core.gui.components.velocity.VelocityContainer; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; @@ -160,7 +161,7 @@ public class LargeFilesController extends FormBasicController implements Extende downloadCountMin, revisionsCountMin, minSize); for(VFSMetadata file:files) { - LargeFilesTableContentRow contentRow = new LargeFilesTableContentRow(file); + LargeFilesTableContentRow contentRow = new LargeFilesTableContentRow(file, getLocale()); String[] path = contentRow.getPath().split("/"); @@ -188,7 +189,7 @@ public class LargeFilesController extends FormBasicController implements Extende downloadCountMin, revisionsCountMin, minSize); for(VFSRevision revision:revisions) { - LargeFilesTableContentRow contentRow = new LargeFilesTableContentRow(revision); + LargeFilesTableContentRow contentRow = new LargeFilesTableContentRow(revision, getLocale()); String[] path = contentRow.getPath().split("/"); @@ -306,6 +307,7 @@ public class LargeFilesController extends FormBasicController implements Extende columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, LargeFilesTableColumns.uuid)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, LargeFilesTableColumns.name, new LargeFilesNameCellRenderer())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, LargeFilesTableColumns.size, new LargeFilesSizeCellRenderer(vfsRepositoryModule))); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, LargeFilesTableColumns.context)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, LargeFilesTableColumns.path)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, LargeFilesTableColumns.age, new LargeFilesAgeCellRenderer())); @@ -401,9 +403,12 @@ public class LargeFilesController extends FormBasicController implements Extende LargeFilesTableContentRow row = (LargeFilesTableContentRow) link.getUserObject(); CalloutSettings settings = new CalloutSettings(false); + VFSContextInfo contextInfo = vfsRepositoryService.getContextInfoFor(row.getPath(), getLocale()); + VelocityContainer pathInfoVC = createVelocityContainer("large_files_path_info"); + pathInfoVC.contextPut("contextInfo", contextInfo); + pathInfoVC.contextPut("row", row); - pathInfoCalloutCtrl = new CloseableCalloutWindowController(ureq, getWindowControl(), - TextFactory.createTextComponentFromString("pathInfo", row.getPath(), "", true, null), link.getFormDispatchId(), "", true, "", settings); + pathInfoCalloutCtrl = new CloseableCalloutWindowController(ureq, getWindowControl(),pathInfoVC, link.getFormDispatchId(), "", true, "", settings); listenTo(pathInfoCalloutCtrl); pathInfoCalloutCtrl.activate(); } diff --git a/src/main/java/org/olat/admin/sysinfo/_content/large_files_path_info.html b/src/main/java/org/olat/admin/sysinfo/_content/large_files_path_info.html new file mode 100644 index 0000000000000000000000000000000000000000..da1fc91d28868db5768219757a8faa01c29ddb21 --- /dev/null +++ b/src/main/java/org/olat/admin/sysinfo/_content/large_files_path_info.html @@ -0,0 +1,7 @@ +<div class='o_nowrap'><strong>$r.translate("vfs.context.name"):</strong> $contextInfo.getContextTitle()</div> +<div class='o_nowrap'><strong>$r.translate("vfs.context.type"):</strong> $contextInfo.getContextTypeName()</div> +<div class='o_nowrap'><strong>$r.translate("largefiles.path"):</strong> $row.getPath() $row.getName()</div> +#if ($contextInfo.getContextUrl()) +<div class="o_nowrap"><strong>$r.translate("vfs.context.url"):</strong> <a href='$contextInfo.getContextUrl()'>$contextInfo.getContextUrl()</a></div> +#end + \ No newline at end of file diff --git a/src/main/java/org/olat/admin/sysinfo/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/admin/sysinfo/_i18n/LocalStrings_de.properties index 0e6fed3885a9c3a063adf25d87ffd52cad26bc1d..cd7e57e480b12239ee2c38e40948feb5f09c563c 100644 --- a/src/main/java/org/olat/admin/sysinfo/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/admin/sysinfo/_i18n/LocalStrings_de.properties @@ -88,6 +88,7 @@ java.threads.title=Gleichzeitige Threads largefiles.age=Alter largefiles.author=Autor largefiles.comment=Kommentar +largefiles.context=Kontext largefiles.createdat=Erstellt am largefiles.creator=Ersteller largefiles.downloads=Downloads @@ -252,3 +253,6 @@ table.header.trigger=Expression title.hibernate.statistics=Hibernate Datenbank Zugriff Statistik title.connection.statistics=Datenbank Connections Statistik usersession.title=Information \u00FCber Benutzer-Sessions +vfs.context.name=Name +vfs.context.type=Typ +vfs.context.url=URL diff --git a/src/main/java/org/olat/admin/sysinfo/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/admin/sysinfo/_i18n/LocalStrings_en.properties index 95c61f2abb6e91ba6b4ff5bf29ed211c9bc7a010..6cfeb16e9848162c8dbbea180c510a2e429141cd 100644 --- a/src/main/java/org/olat/admin/sysinfo/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/admin/sysinfo/_i18n/LocalStrings_en.properties @@ -88,6 +88,7 @@ java.threads.title=Current threads largefiles.age=Age largefiles.author=Author largefiles.comment=Comment +largefiles.context=Context largefiles.createdat=Created largefiles.creator=Creator largefiles.downloads=Downloads @@ -252,3 +253,7 @@ table.header.trigger=Expression title.connection.statistics=Database connections statistics title.hibernate.statistics=Hibernate database access statistics usersession.title=Information on user sessions +vfs.context.name=Name +vfs.context.type=Type +vfs.context.url=URL + diff --git a/src/main/java/org/olat/admin/sysinfo/model/LargeFilesTableContentRow.java b/src/main/java/org/olat/admin/sysinfo/model/LargeFilesTableContentRow.java index 7d7fcd18cbcb8b2c0fe1fff6674ff5cdac970f8c..684b46817d024c5f17f9ccf0e039235dbf6a5f10 100644 --- a/src/main/java/org/olat/admin/sysinfo/model/LargeFilesTableContentRow.java +++ b/src/main/java/org/olat/admin/sysinfo/model/LargeFilesTableContentRow.java @@ -21,10 +21,14 @@ package org.olat.admin.sysinfo.model; import java.util.Calendar; import java.util.Date; +import java.util.Locale; +import org.olat.core.CoreSpringFactory; import org.olat.core.commons.services.license.LicenseType; import org.olat.core.commons.services.vfs.VFSMetadata; +import org.olat.core.commons.services.vfs.VFSRepositoryService; import org.olat.core.commons.services.vfs.VFSRevision; +import org.olat.core.commons.services.vfs.impl.VFSContextInfoUnknownPathResolver; import org.olat.core.gui.components.form.flexible.elements.FormLink; import org.olat.core.id.Identity; import org.olat.core.util.WebappHelper; @@ -42,6 +46,7 @@ public class LargeFilesTableContentRow { private final Long size; private FormLink pathInfo; private final String path; + private final String context; private final Identity author; private final boolean revision; private final String fileType; @@ -65,12 +70,14 @@ public class LargeFilesTableContentRow { private final long revisionNr; private final String revisionComment; - public LargeFilesTableContentRow(VFSMetadata metadata) { + public LargeFilesTableContentRow(VFSMetadata metadata, Locale locale) { key = metadata.getKey(); name = metadata.getFilename(); size = metadata.getFileSize(); author = metadata.getAuthor(); path = metadata.getRelativePath(); + VFSRepositoryService vfsRepositoryService = CoreSpringFactory.getImpl(VFSRepositoryService.class); + context = vfsRepositoryService.getContextTypeFor(path, locale); fileType = WebappHelper.getMimeType(metadata.getFilename()) != null ? WebappHelper.getMimeType(metadata.getFilename()).split("/")[1] : "Unknown"; fileCategory = WebappHelper.getMimeType(metadata.getFilename()) != null ? WebappHelper.getMimeType(metadata.getFilename()).split("/")[0] : "Unknown"; revision = false; @@ -94,12 +101,14 @@ public class LargeFilesTableContentRow { revisionComment = metadata.getRevisionComment(); } - public LargeFilesTableContentRow(VFSRevision rev) { + public LargeFilesTableContentRow(VFSRevision rev, Locale locale) { key = rev.getMetadata().getKey(); name = rev.getFilename(); size = rev.getSize(); author = rev.getAuthor(); path = rev.getMetadata().getRelativePath(); + VFSRepositoryService vfsRepositoryService = CoreSpringFactory.getImpl(VFSRepositoryService.class); + context = vfsRepositoryService.getContextTypeFor(path, locale); revision = true; fileType = WebappHelper.getMimeType(rev.getFilename()) != null ? WebappHelper.getMimeType(rev.getFilename()).split("/")[1] : "Unknown"; fileCategory = WebappHelper.getMimeType(rev.getFilename()) != null ? WebappHelper.getMimeType(rev.getFilename()).split("/")[0] : "Unknown"; @@ -172,6 +181,13 @@ public class LargeFilesTableContentRow { return path; } + public String getContext() { + if (context == null || context.equals(VFSContextInfoUnknownPathResolver.UNKNOWN_TYPE)) { + return path; + } + return context; + } + public Boolean isRevision() { return revision; } diff --git a/src/main/java/org/olat/admin/sysinfo/model/LargeFilesTableModel.java b/src/main/java/org/olat/admin/sysinfo/model/LargeFilesTableModel.java index eb5c1d2d6703d4189095bb4a569f0132b347920e..943c83a61313d1ed4fa96d92ed5652d4cb6a5d92 100644 --- a/src/main/java/org/olat/admin/sysinfo/model/LargeFilesTableModel.java +++ b/src/main/java/org/olat/admin/sysinfo/model/LargeFilesTableModel.java @@ -69,6 +69,7 @@ implements SortableFlexiTableDataModel<LargeFilesTableContentRow> { case name: return row.getName(); case size: return row.getSize(); case path: return row.getPathInfo(); + case context: return row.getContext(); case author: return row.getAuthor() != null ? row.getAuthor().getUser().getFirstName() + " " + row.getAuthor().getUser().getLastName() : null; case revision: return row.isRevision(); case fileCategory: return row.getFileCategory(); @@ -115,6 +116,7 @@ implements SortableFlexiTableDataModel<LargeFilesTableContentRow> { name("largefiles.name"), size("largefiles.size"), path("largefiles.path"), + context("largefiles.context"), author("largefiles.author"), revision("largefiles.revision"), fileType("largefiles.filetype"), diff --git a/src/main/java/org/olat/collaboration/CollaborationToolsFolderVFSContextInfoResolver.java b/src/main/java/org/olat/collaboration/CollaborationToolsFolderVFSContextInfoResolver.java new file mode 100644 index 0000000000000000000000000000000000000000..878ddffd3efce42c19145b9eefbdff1dba578919 --- /dev/null +++ b/src/main/java/org/olat/collaboration/CollaborationToolsFolderVFSContextInfoResolver.java @@ -0,0 +1,114 @@ +/** + * <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.collaboration; + +import java.util.List; +import java.util.Locale; + +import org.apache.logging.log4j.Logger; +import org.olat.core.commons.services.vfs.VFSContextInfo; +import org.olat.core.commons.services.vfs.VFSContextInfoResolver; +import org.olat.core.commons.services.vfs.impl.VFSContextInfoImpl; +import org.olat.core.id.context.BusinessControlFactory; +import org.olat.core.id.context.ContextEntry; +import org.olat.core.logging.Tracing; +import org.olat.core.util.StringHelper; +import org.olat.core.util.Util; +import org.olat.group.BusinessGroup; +import org.olat.group.BusinessGroupService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Service; + +/** + * + * Initial date: 16 Jan 2020<br> + * + * @author gnaegi, gnaegi@frentix.com, http://www.frentix.com + * + */ +@Service +@Order(value=300) +public class CollaborationToolsFolderVFSContextInfoResolver implements VFSContextInfoResolver { + private static final Logger log = Tracing.createLoggerFor(CollaborationToolsFolderVFSContextInfoResolver.class); + + @Autowired + private BusinessGroupService bgService; + + + @Override + public String resolveContextTypeName(String vfsMetadataRelativePath, Locale locale) { + if (vfsMetadataRelativePath == null) { + return null; + } + String type = null; + // Is either a transcoding or the master video + if (vfsMetadataRelativePath.startsWith("cts")) { + if (vfsMetadataRelativePath.startsWith("cts/folders")) { + type = Util.createPackageTranslator(CollaborationToolsFolderVFSContextInfoResolver.class, locale).translate("vfs.context.cts.folders"); + } else if (vfsMetadataRelativePath.startsWith("cts/wikis")) { + type = Util.createPackageTranslator(CollaborationToolsFolderVFSContextInfoResolver.class, locale).translate("vfs.context.cts.wikis"); + } + } + return type; + } + + @Override + public VFSContextInfo resolveContextInfo(String vfsMetadataRelativePath, Locale locale) { + String type = resolveContextTypeName(vfsMetadataRelativePath, locale); + if (type == null) { + return null; + } + + // Try finding detail infos. Path looks something like this cts/[tooltype]/BusinessGroup/[groupid]/... + String name = "Unknown"; + String url = null; + + String[] path = vfsMetadataRelativePath.split("/"); + if (path.length < 4) { + return null; // no idea + } + String keyString = path[3]; + // lookup group resource + if (StringHelper.isLong(keyString)) { + + BusinessGroup businessGroup = bgService.loadBusinessGroup(Long.valueOf(keyString)); + + if (businessGroup == null) { + log.warn("No group found for id::" + keyString + " for path::" + vfsMetadataRelativePath); + } else { + name = businessGroup.getName(); + BusinessControlFactory bcf = BusinessControlFactory.getInstance(); + List<ContextEntry> entries = bcf.createCEListFromString("[BusinessGroup:" + businessGroup.getKey() + "]"); + if (path[1].equals("folders")) { + entries.addAll(bcf.createCEListFromString("[toolfolder:0]")); + // TODO: add other path elements to subdirectory + } else if (path[1].equals("wikis")) { + entries.addAll(bcf.createCEListFromString("[wiki:0]")); + } + url = bcf.getAsURIString(entries, true); + } + } else { + log.warn("Can not parse group id for path::{}", vfsMetadataRelativePath); + } + return new VFSContextInfoImpl(type, name, url); + } + +} diff --git a/src/main/java/org/olat/collaboration/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/collaboration/_i18n/LocalStrings_de.properties index d77c2b366231cc3bc5abc1f7fc85e21022cfeca5..fbdd32ab0629c30b7cfee9ab6e3de25b7e598952 100644 --- a/src/main/java/org/olat/collaboration/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/collaboration/_i18n/LocalStrings_de.properties @@ -22,3 +22,5 @@ folder.access.title=Ordner Schreibberechtigung konfigurieren news.access=Informationen Schreibberechtigung news.content=Information an Mitglieder selection=Auswahl +vfs.context.cts.folders=Gruppen-Ordner +vfs.context.cts.wikis=Gruppen-Wiki \ No newline at end of file diff --git a/src/main/java/org/olat/collaboration/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/collaboration/_i18n/LocalStrings_en.properties index f20d59f6f3dc57f7530a66173796104e9610a3be..98095422dd12a084de2858b16228d4a4e4edc7a3 100644 --- a/src/main/java/org/olat/collaboration/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/collaboration/_i18n/LocalStrings_en.properties @@ -22,3 +22,5 @@ folder.access.title=Configure folder write permission news.access=News write permission news.content=Information for members selection=Selection +vfs.context.cts.folders=Group folder +vfs.context.cts.wikis=Group wiki \ No newline at end of file diff --git a/src/main/java/org/olat/core/commons/services/vfs/VFSContextInfo.java b/src/main/java/org/olat/core/commons/services/vfs/VFSContextInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..d2003faa67ae755032fdab093808f142bfb902e0 --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/vfs/VFSContextInfo.java @@ -0,0 +1,54 @@ +/** + * <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.core.commons.services.vfs; + +/** + * Describes the context of a VFS item for display purposes. The + * context info is localized for the current user. + * + * Initial date: 16 Jan 2020<br> + * + * @author gnaegi, gnaegi@frentix.com, http://www.frentix.com + * + */ +public interface VFSContextInfo { + + /** + * The type of the context / file, e.g. "Home folder" + * + * @return + */ + public String getContextTypeName(); + + /** + * The specific name, e.g. course element + * + * @return + */ + public String getContextTitle(); + + /** + * The URL to open this context within OpenOlat or NULL if not applicable + * + * @return + */ + public String getContextUrl(); + +} diff --git a/src/main/java/org/olat/core/commons/services/vfs/VFSContextInfoResolver.java b/src/main/java/org/olat/core/commons/services/vfs/VFSContextInfoResolver.java new file mode 100644 index 0000000000000000000000000000000000000000..b41933ece68707a0005fc6936ec1eaeed79e2e1d --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/vfs/VFSContextInfoResolver.java @@ -0,0 +1,55 @@ +/** + * <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.core.commons.services.vfs; + +import java.util.Locale; + +/** + * + * Initial date: 16 Jan 2020<br> + * + * @author gnaegi, gnaegi@frentix.com, http://www.frentix.com + * + */ +public interface VFSContextInfoResolver { + + /** + * Resolve the localized type name for a give file path. This method is "light + * weight" without any db access, resolving is done by applying some regexp on + * the path. + * + * @param VFSMetadataRelativePath the relative file path + * @param locale The user locale + * @return The localized type name or NULL if not resolvable by this resolver + */ + public String resolveContextTypeName(String VFSMetadataRelativePath, Locale locale); + + + /** + * Resolve the localized context info for a give file path. This method will do + * db queries to build the context info. + * + * @param VFSMetadataRelativePath the relative file path + * @param locale The user locale + * @return The localized context info or NULL if not resolvable by this resolver + */ + public VFSContextInfo resolveContextInfo(String VFSMetadataRelativePath, Locale locale); + +} diff --git a/src/main/java/org/olat/core/commons/services/vfs/VFSRepositoryService.java b/src/main/java/org/olat/core/commons/services/vfs/VFSRepositoryService.java index 889c0278cdfc07679bc620c4c925eee6b9d9877a..d3c1c590f4a19cf46ed5f4b277d1a029c08ccfaa 100644 --- a/src/main/java/org/olat/core/commons/services/vfs/VFSRepositoryService.java +++ b/src/main/java/org/olat/core/commons/services/vfs/VFSRepositoryService.java @@ -23,6 +23,7 @@ import java.io.File; import java.io.InputStream; import java.util.Date; import java.util.List; +import java.util.Locale; import org.olat.core.commons.services.license.License; import org.olat.core.commons.services.vfs.model.VFSFileStatistics; @@ -45,6 +46,29 @@ public interface VFSRepositoryService { public VFSMetadata getMetadataFor(File file); + /** + * Resolve the context type for the given metadata. This method is "light + * weight" and does not trigger database queries + * + * @param relativePath The vfs metadada relative path for which the context is + * resolved + * @param locale The users locale + * @return A localized string or "Unknown" if not resolved + */ + public String getContextTypeFor(String relativePath, Locale locale); + + /** + * Resolve and build the detailed context information for the given metadata. + * This methods is "heavy weight" and might user multiple database queries to + * lookup all information. Use this only to lookup individual items. + * + * @param relativePath The vfs metadada relative path for which the context is + * resolved + * @param locale The users locale + * @return The resolved and localized context or the VFSContextInfoUnknown + */ + public VFSContextInfo getContextInfoFor(String relativePath, Locale locale); + public VFSMetadata getMetadata(VFSMetadataRef ref); public VFSMetadata getMetadataByUUID(String uuid); diff --git a/src/main/java/org/olat/core/commons/services/vfs/impl/VFSContextInfoImpl.java b/src/main/java/org/olat/core/commons/services/vfs/impl/VFSContextInfoImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..01f831d34d3777a8f4bfa51573278988d058ba60 --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/vfs/impl/VFSContextInfoImpl.java @@ -0,0 +1,56 @@ +/** + * <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.core.commons.services.vfs.impl; + +import org.olat.core.commons.services.vfs.VFSContextInfo; + +/** + * + * Initial date: 16 Jan 2020<br> + * + * @author gnaegi, gnaegi@frentix.com, http://www.frentix.com + * + */ +public class VFSContextInfoImpl implements VFSContextInfo { + private String contextTypeName; + private String contextTitle; + private String contextUrl; + + public VFSContextInfoImpl(String contextTypeName, String contextTitle, String contextUrl) { + this.contextTypeName = contextTypeName; + this.contextTitle = contextTitle; + this.contextUrl = contextUrl; + } + + @Override + public String getContextTypeName() { + return contextTypeName; + } + + @Override + public String getContextTitle() { + return contextTitle; + } + + @Override + public String getContextUrl() { + return contextUrl; + } +} diff --git a/src/main/java/org/olat/core/commons/services/vfs/impl/VFSContextInfoUnknown.java b/src/main/java/org/olat/core/commons/services/vfs/impl/VFSContextInfoUnknown.java new file mode 100644 index 0000000000000000000000000000000000000000..09eec69e281c9373140224254c817c256bca85d3 --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/vfs/impl/VFSContextInfoUnknown.java @@ -0,0 +1,34 @@ +/** + * <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.core.commons.services.vfs.impl; + +/** + * Default context resolver for contexts that are not yet implemented + * + * Initial date: 16 Jan 2020<br> + * @author gnaegi, gnaegi@frentix.com, http://www.frentix.com + * + */ +public class VFSContextInfoUnknown extends VFSContextInfoImpl { + + public VFSContextInfoUnknown(String reason) { + super("Unknown", reason, null); + } +} diff --git a/src/main/java/org/olat/core/commons/services/vfs/impl/VFSContextInfoUnknownPathResolver.java b/src/main/java/org/olat/core/commons/services/vfs/impl/VFSContextInfoUnknownPathResolver.java new file mode 100644 index 0000000000000000000000000000000000000000..c7cafc09e6e8fb9876534442b5133662850cd5c8 --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/vfs/impl/VFSContextInfoUnknownPathResolver.java @@ -0,0 +1,55 @@ +/** + * <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.core.commons.services.vfs.impl; + +import java.util.Locale; + +import org.olat.core.commons.services.vfs.VFSContextInfo; +import org.olat.core.commons.services.vfs.VFSContextInfoResolver; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +/** + * Don't remove this, is used as default resolver when no other resolver matches + * + * Initial date: 16 Jan 2020<br> + * + * @author gnaegi, gnaegi@frentix.com, http://www.frentix.com + * + */ +@Component +@Order(Ordered.LOWEST_PRECEDENCE) +public class VFSContextInfoUnknownPathResolver implements VFSContextInfoResolver { + public static final String UNKNOWN_TYPE = "Unknown"; + public static final String UNKNOWN_CONTEXT = "Unknown Context"; + + + @Override + public String resolveContextTypeName(String VFSMetadataRelativePath, Locale locale) { + return UNKNOWN_TYPE; + } + + @Override + public VFSContextInfo resolveContextInfo(String VFSMetadataRelativePath, Locale locale) { + return new VFSContextInfoUnknown(UNKNOWN_CONTEXT); + } + +} diff --git a/src/main/java/org/olat/core/commons/services/vfs/manager/VFSRepositoryServiceImpl.java b/src/main/java/org/olat/core/commons/services/vfs/manager/VFSRepositoryServiceImpl.java index 20706f2a363a476a2d9a99c1d3b4b2600723fd3d..d6ff01b2a498c6ed37808b053dda13c71819b3c8 100644 --- a/src/main/java/org/olat/core/commons/services/vfs/manager/VFSRepositoryServiceImpl.java +++ b/src/main/java/org/olat/core/commons/services/vfs/manager/VFSRepositoryServiceImpl.java @@ -41,6 +41,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; @@ -61,6 +62,8 @@ import org.olat.core.commons.services.license.LicenseType; import org.olat.core.commons.services.thumbnail.CannotGenerateThumbnailException; import org.olat.core.commons.services.thumbnail.FinalSize; import org.olat.core.commons.services.thumbnail.ThumbnailService; +import org.olat.core.commons.services.vfs.VFSContextInfo; +import org.olat.core.commons.services.vfs.VFSContextInfoResolver; import org.olat.core.commons.services.vfs.VFSFilterKeys; import org.olat.core.commons.services.vfs.VFSMetadata; import org.olat.core.commons.services.vfs.VFSMetadataRef; @@ -70,6 +73,8 @@ import org.olat.core.commons.services.vfs.VFSRevision; import org.olat.core.commons.services.vfs.VFSRevisionRef; import org.olat.core.commons.services.vfs.VFSThumbnailMetadata; import org.olat.core.commons.services.vfs.VFSVersionModule; +import org.olat.core.commons.services.vfs.impl.VFSContextInfoUnknown; +import org.olat.core.commons.services.vfs.impl.VFSContextInfoUnknownPathResolver; import org.olat.core.commons.services.vfs.manager.MetaInfoReader.Thumbnail; import org.olat.core.commons.services.vfs.model.VFSFileStatistics; import org.olat.core.commons.services.vfs.model.VFSMetadataImpl; @@ -141,6 +146,8 @@ public class VFSRepositoryServiceImpl implements VFSRepositoryService, GenericEv private CoordinatorManager coordinatorManager; @Autowired private BaseSecurity securityManager; + // Autowired liste by setVfsContextInfoResolver() method + private List<VFSContextInfoResolver> vfsContextInfoResolver; @Override public void afterPropertiesSet() throws Exception { @@ -285,6 +292,34 @@ public class VFSRepositoryServiceImpl implements VFSRepositoryService, GenericEv return metadata; } + @Override + public String getContextTypeFor(String relativePath, Locale locale) { + if (relativePath == null) { + return "No path"; + } + for (VFSContextInfoResolver resolver : vfsContextInfoResolver) { + String contextType = resolver.resolveContextTypeName(relativePath, locale); + if (contextType != null) { + return contextType; + } + } + return VFSContextInfoUnknownPathResolver.UNKNOWN_TYPE; + } + + @Override + public VFSContextInfo getContextInfoFor(String relativePath, Locale locale) { + if (relativePath == null) { + new VFSContextInfoUnknown("No Relative Path"); + } + for (VFSContextInfoResolver resolver : vfsContextInfoResolver) { + VFSContextInfo contextInfo = resolver.resolveContextInfo(relativePath, locale); + if (contextInfo != null) { + return contextInfo; + } + } + return new VFSContextInfoUnknown(VFSContextInfoUnknownPathResolver.UNKNOWN_CONTEXT); + } + @Override public VFSItem getItemFor(VFSMetadata metadata) { if(metadata == null) return null; @@ -1540,4 +1575,15 @@ public class VFSRepositoryServiceImpl implements VFSRepositoryService, GenericEv public VFSThumbnailStatistics getThumbnailStats() { return statsDao.getThumbnailStats(); } + + + /** + * Set list of context info resolver. Used to autowire resolvers from various implementers + * @param vfsContextInfoResolver + */ + @Autowired + public void setVfsContextInfoResolvers(List<VFSContextInfoResolver> vfsContextInfoResolver) { + this.vfsContextInfoResolver = vfsContextInfoResolver; + } + } diff --git a/src/main/java/org/olat/course/CourseVFSContextInfoResolver.java b/src/main/java/org/olat/course/CourseVFSContextInfoResolver.java new file mode 100644 index 0000000000000000000000000000000000000000..8bdd820e5b27d6f0a89a961f4384351ffe01e820 --- /dev/null +++ b/src/main/java/org/olat/course/CourseVFSContextInfoResolver.java @@ -0,0 +1,116 @@ +/** + * <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.course; + +import java.util.List; +import java.util.Locale; + +import org.apache.logging.log4j.Logger; +import org.olat.core.commons.services.vfs.VFSContextInfo; +import org.olat.core.commons.services.vfs.impl.VFSContextInfoImpl; +import org.olat.core.helpers.Settings; +import org.olat.core.logging.Tracing; +import org.olat.core.util.StringHelper; +import org.olat.core.util.Util; +import org.olat.repository.RepositoryEntry; +import org.olat.repository.RepositoryEntryVFSContextInfoResolver; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Service; + +/** + * + * A specialized version of the repository entry resolver that catches the + * course resources. Since courses are special, they are not located in the + * standard repository directory but have their own. + * <br /> + * The class inheritence is not necessary, it just shows that this belongs to + * the repository. + * + * + * Initial date: 16 Jan 2020<br> + * + * @author gnaegi, gnaegi@frentix.com, http://www.frentix.com + * + */ +@Service +@Order(value=100) +public class CourseVFSContextInfoResolver extends RepositoryEntryVFSContextInfoResolver { + private static final Logger log = Tracing.createLoggerFor(CourseVFSContextInfoResolver.class); + + @Override + public String resolveContextTypeName(String vfsMetadataRelativePath, Locale locale) { + if (vfsMetadataRelativePath == null) { + return null; + } + String type = null; + // Is either a transcoding or the master video + if (vfsMetadataRelativePath.startsWith(PersistingCourseImpl.COURSE_ROOT_DIR_NAME)) { + if (vfsMetadataRelativePath.contains(PersistingCourseImpl.COURSEFOLDER)) { + type = Util.createPackageTranslator(CourseVFSContextInfoResolver.class, locale).translate("vfs.context.coursefolder"); + } else if (vfsMetadataRelativePath.contains("foldernodes")) { + type = Util.createPackageTranslator(CourseVFSContextInfoResolver.class, locale).translate("vfs.context.foldernodes"); + } + } + return type; + } + + @Override + public VFSContextInfo resolveContextInfo(String vfsMetadataRelativePath, Locale locale) { + String type = resolveContextTypeName(vfsMetadataRelativePath, locale); + if (type == null) { + return null; + } + + // Try finding detail infos + String name = "Unknown"; + String url = null; + + String[] path = vfsMetadataRelativePath.split("/"); + String keyString = path[1]; + if (StringHelper.isLong(keyString)) { + List<RepositoryEntry> repoEntries = repositoryService.searchByIdAndRefs(keyString); + if (repoEntries.size() != 1) { + log.warn("No olat resource resource found for id::{} for path::{}", keyString, vfsMetadataRelativePath); + } else { + RepositoryEntry re = repoEntries.get(0); + if (re == null) { + log.warn("No repository entry found for key::{} for path::{}", keyString, vfsMetadataRelativePath); + } else { + name = re.getDisplayname(); + url = Settings.getServerContextPathURI() + "/url/RepositoryEntry/" + re.getKey(); + + if (path.length >= 4 && PersistingCourseImpl.COURSEFOLDER.equals(path[2])) { + // Add direct path to course folder + // TODO: add other path elements to subdirectory + url += "/path%3D~~/0"; + } else if (path.length >= 4 && "foldernodes".equals(path[2])) { + // Add course node jump in if available + url += "/CourseNode" + path[3]; + } + } + } + } else { + log.warn("Can not parse repo entry id for path::{}", vfsMetadataRelativePath); + } + + return new VFSContextInfoImpl(type, name, url); + } + +} diff --git a/src/main/java/org/olat/course/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/_i18n/LocalStrings_de.properties index 21005030ac3e81e323790ec81c8cf3add44074ac..798b99d915b555ad9bc49a2a224ebf072a5637db 100644 --- a/src/main/java/org/olat/course/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/course/_i18n/LocalStrings_de.properties @@ -12,3 +12,5 @@ course.times.loaded=Aufrufe course.title=Titel current.active.user=Aktiv error.helpcourse.not.configured=In diesem System steht keine Hilfe zur Verf\u00FCgung. +vfs.context.coursefolder=Kurs Ablageordner +vfs.context.foldernodes=Kursbaustein Daten \ No newline at end of file diff --git a/src/main/java/org/olat/course/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/_i18n/LocalStrings_en.properties index 42e18705d2209d6660e770ee6de70b5f78773e6a..4bab508f42523d28ae1b31589b1d93694ef42523 100644 --- a/src/main/java/org/olat/course/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/course/_i18n/LocalStrings_en.properties @@ -12,3 +12,5 @@ course.times.loaded=Calls course.title=Title current.active.user=Active error.helpcourse.not.configured=This system does not provide any help feature. +vfs.context.coursefolder=Course folder +vfs.context.foldernodes=Course element data diff --git a/src/main/java/org/olat/home/PersonalFolderVFSContextInfoResolver.java b/src/main/java/org/olat/home/PersonalFolderVFSContextInfoResolver.java new file mode 100644 index 0000000000000000000000000000000000000000..7d45b7d61a136f3240dc6cac6a1846624188e8c1 --- /dev/null +++ b/src/main/java/org/olat/home/PersonalFolderVFSContextInfoResolver.java @@ -0,0 +1,92 @@ +/** + * <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.home; + +import java.util.Locale; + +import org.apache.logging.log4j.Logger; +import org.olat.basesecurity.BaseSecurityManager; +import org.olat.core.commons.services.vfs.VFSContextInfo; +import org.olat.core.commons.services.vfs.VFSContextInfoResolver; +import org.olat.core.commons.services.vfs.impl.VFSContextInfoImpl; +import org.olat.core.helpers.Settings; +import org.olat.core.id.Identity; +import org.olat.core.logging.Tracing; +import org.olat.core.util.Util; +import org.olat.user.UserManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +/** + * + * Initial date: 16 Jan 2020<br> + * + * @author gnaegi, gnaegi@frentix.com, http://www.frentix.com + * + */ +@Component +@Order(value=400) +public class PersonalFolderVFSContextInfoResolver implements VFSContextInfoResolver { + private static final Logger log = Tracing.createLoggerFor(PersonalFolderVFSContextInfoResolver.class); + + @Autowired + private BaseSecurityManager baseSecurityMgr; + + @Override + public String resolveContextTypeName(String vfsMetadataRelativePath, Locale locale) { + if (vfsMetadataRelativePath == null) { + return null; + } + String type = null; + // Is either a transcoding or the master video + if (vfsMetadataRelativePath.startsWith("homes")) { + type = Util.createPackageTranslator(PersonalFolderVFSContextInfoResolver.class, locale).translate("vfs.context.homes"); + } + return type; + } + + @Override + public VFSContextInfo resolveContextInfo(String vfsMetadataRelativePath, Locale locale) { + String type = resolveContextTypeName(vfsMetadataRelativePath, locale); + if (type == null) { + return null; + } + + // Try finding detail infos + String name = "Unknown"; + String url = null; + + String[] path = vfsMetadataRelativePath.split("/"); + String keyString = path[1]; + Identity identity = baseSecurityMgr.findIdentityByName(keyString); + if (identity == null) { + log.warn("No identity found for id::{} for path::{}", keyString, vfsMetadataRelativePath); + } else { + name = UserManager.getInstance().getUserDisplayName(identity); + url = Settings.getServerContextPathURI() + "/auth/HomeSite/" + identity.getKey() + "/userfolder/0"; + // TODO: add other path elements to subdirectory + + } + + return new VFSContextInfoImpl(type, name, url); + } + +} diff --git a/src/main/java/org/olat/home/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/home/_i18n/LocalStrings_de.properties index c5515fa8ee83cc648285a395315aaaeef1537b21..2ba24380fb79074588174006a0076aca9406ffe2 100644 --- a/src/main/java/org/olat/home/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/home/_i18n/LocalStrings_de.properties @@ -59,3 +59,5 @@ warn.session.was.killed=Sie hatten OpenOlat bereits in einem anderen Browser off welcome.header=Willkommen bei OpenOlat welcome.intro=<\!-- --> welcome.rss=Lesen Sie Ihre pers\u00F6nlichen News als RSS-Feed +vfs.context.homes=$\:menu.bc + diff --git a/src/main/java/org/olat/home/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/home/_i18n/LocalStrings_en.properties index 4251c1857e5793c1e747eb20934c24326ca08b8f..a8e9c582aee7e088dbaa12e412edff33ece20fbb 100644 --- a/src/main/java/org/olat/home/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/home/_i18n/LocalStrings_en.properties @@ -59,3 +59,4 @@ warn.session.was.killed=You are using OpenOlat in another browser. You cannot lo welcome.header=Welcome to OpenOlat welcome.intro=<\!-- --> welcome.rss=Read your personal news as RSS Feed +vfs.context.homes=$\:menu.bc diff --git a/src/main/java/org/olat/modules/video/manager/VideoVFSContextInfoResolver.java b/src/main/java/org/olat/modules/video/manager/VideoVFSContextInfoResolver.java new file mode 100644 index 0000000000000000000000000000000000000000..4a64f6ff86914adc5d9c68b52dcb02fe3d49b3a2 --- /dev/null +++ b/src/main/java/org/olat/modules/video/manager/VideoVFSContextInfoResolver.java @@ -0,0 +1,103 @@ +/** + * <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.video.manager; + +import java.util.List; +import java.util.Locale; + +import org.apache.logging.log4j.Logger; +import org.olat.core.commons.services.vfs.VFSContextInfo; +import org.olat.core.commons.services.vfs.impl.VFSContextInfoImpl; +import org.olat.core.helpers.Settings; +import org.olat.core.logging.Tracing; +import org.olat.core.util.StringHelper; +import org.olat.core.util.Util; +import org.olat.modules.video.ui.VideoDisplayController; +import org.olat.repository.RepositoryEntry; +import org.olat.repository.RepositoryEntryVFSContextInfoResolver; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Service; + +/** + * A specialized version of the repository entry resolver that catches also the + * transcoded video resources. This resolver has a higher order value to be + * executed before the default repository resolver. + * <br /> + * The class inheritence is not necessary, it just shows that this belongs to the repository + * + * Initial date: 16 Jan 2020<br> + * + * @author gnaegi, gnaegi@frentix.com, http://www.frentix.com + * + */ +@Service +@Order(value=200) +public class VideoVFSContextInfoResolver extends RepositoryEntryVFSContextInfoResolver { + private static final Logger log = Tracing.createLoggerFor(VideoVFSContextInfoResolver.class); + + @Override + public String resolveContextTypeName(String vfsMetadataRelativePath, Locale locale) { + if (vfsMetadataRelativePath == null) { + return null; + } + String type = null; + // Is either a transcoding or the master video + if (vfsMetadataRelativePath.startsWith("transcodedVideos")) { + type = Util.createPackageTranslator(VideoDisplayController.class, locale).translate("admin.menu.transcoding.title"); + } else if (vfsMetadataRelativePath.startsWith("repository") && vfsMetadataRelativePath.endsWith("master")) { + type = Util.createPackageTranslator(VideoDisplayController.class, locale).translate("quality.master"); + } + return type; + } + + @Override + public VFSContextInfo resolveContextInfo(String vfsMetadataRelativePath, Locale locale) { + String type = resolveContextTypeName(vfsMetadataRelativePath, locale); + if (type == null) { + return null; + } + + // Try finding detail infos + String name = "Unknown"; + String url = null; + + String[] path = vfsMetadataRelativePath.split("/"); + String keyString = path[1]; + if (StringHelper.isLong(keyString)) { + List<RepositoryEntry> repoEntries = repositoryService.searchByIdAndRefs(keyString); + if (repoEntries.size() != 1) { + log.warn("No olat resource resource found for id::" + keyString + " for path::" + vfsMetadataRelativePath); + } else { + RepositoryEntry re = repoEntries.get(0); + if (re == null) { + log.warn("No repository entry found for key::" + keyString + " for path::" + vfsMetadataRelativePath); + } else { + name = re.getDisplayname(); + url = Settings.getServerContextPathURI() + "/url/RepositoryEntry/" + re.getKey(); + } + } + } else { + log.warn("Can not parse repo entry id for path::{}", vfsMetadataRelativePath); + } + + return new VFSContextInfoImpl(type, name, url); + } + +} diff --git a/src/main/java/org/olat/repository/RepositoryEntryVFSContextInfoResolver.java b/src/main/java/org/olat/repository/RepositoryEntryVFSContextInfoResolver.java new file mode 100644 index 0000000000000000000000000000000000000000..b4357c356c3760d0280444439ccef332550d4468 --- /dev/null +++ b/src/main/java/org/olat/repository/RepositoryEntryVFSContextInfoResolver.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.repository; + +import java.util.List; +import java.util.Locale; + +import org.apache.logging.log4j.Logger; +import org.olat.core.commons.services.vfs.VFSContextInfo; +import org.olat.core.commons.services.vfs.VFSContextInfoResolver; +import org.olat.core.commons.services.vfs.impl.VFSContextInfoImpl; +import org.olat.core.helpers.Settings; +import org.olat.core.logging.Tracing; +import org.olat.core.util.StringHelper; +import org.olat.core.util.Util; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +/** + * A generic repository resolver that catches everything that has not been + * resolved by a more specific resolver with the higher order + * + * Initial date: 16 Jan 2020<br> + * + * @author gnaegi, gnaegi@frentix.com, http://www.frentix.com + * + */ +@Component +@Order(value=10000) +public class RepositoryEntryVFSContextInfoResolver implements VFSContextInfoResolver { + private static final Logger log = Tracing.createLoggerFor(RepositoryEntryVFSContextInfoResolver.class); + + @Autowired + protected RepositoryService repositoryService; + + @Override + public String resolveContextTypeName(String vfsMetadataRelativePath, Locale locale) { + if (vfsMetadataRelativePath == null) { + return null; + } + String type = null; + // Catch all repo entry path + if (vfsMetadataRelativePath.startsWith("repository")){ + type = Util.createPackageTranslator(RepositoryEntryVFSContextInfoResolver.class, locale).translate("vfs.context.repositoryentry"); + } + return type; + } + + @Override + public VFSContextInfo resolveContextInfo(String vfsMetadataRelativePath, Locale locale) { + String type = resolveContextTypeName(vfsMetadataRelativePath, locale); + if (type == null) { + return null; + } + + // Try finding detail infos + String name = "Unknown"; + String url = null; + + String[] path = vfsMetadataRelativePath.split("/"); + String keyString = path[1]; + if (StringHelper.isLong(keyString)) { + + List<RepositoryEntry> repoEntries = repositoryService.searchByIdAndRefs(keyString); + if (repoEntries.size() != 1) { + log.warn("No olat resource resource found for id::" + keyString + " for path::" + vfsMetadataRelativePath); + } else { + RepositoryEntry re = repoEntries.get(0); + name = re.getDisplayname(); + url = Settings.getServerContextPathURI() + "/url/RepositoryEntry/" + re.getKey(); + type = Util.createPackageTranslator(RepositoryEntryVFSContextInfoResolver.class, locale).translate(re.getOlatResource().getResourceableTypeName()); + } + } else { + log.warn("Can not parse repo entry id for path::{}", vfsMetadataRelativePath); + } + + return new VFSContextInfoImpl(type, name, url); + } + +} diff --git a/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties index 4169bc91ee15ab6fe40fd3ee4ecd06af1b0e2f21..c0e2f2fe2dd3aa2eaacd42d35cbd53f91d016ed2 100644 --- a/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties @@ -752,3 +752,4 @@ wizardsteptitledescription=Beschreibung eintragen wizardsteptitleproperties=Einstellungen vornehmen wizardsteptitleupload=Datei hochladen year=Jahr +vfs.context.repositoryentry=Lernressource diff --git a/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties index 12eb065e4fccb58dd8b05a1fca94a1b29c2777a7..0cfc2f655c7c4e199334ae2cd3224a13e78a0054 100644 --- a/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties @@ -752,3 +752,5 @@ wizardsteptitledescription=Indicate description wizardsteptitleproperties=Set properties wizardsteptitleupload=Upload file year=Year +vfs.context.repositoryentry=Learning resource +