Newer
Older
/**
* <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.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.olat.core.CoreSpringFactory;
import org.olat.core.commons.persistence.DBFactory;
import org.olat.core.commons.services.webdav.WebDAVModule;
import org.olat.core.commons.services.webdav.manager.WebDAVMergeSource;
import org.olat.core.commons.services.webdav.servlets.RequestUtil;
import org.olat.core.id.IdentityEnvironment;
import org.olat.core.util.StringHelper;
import org.olat.core.util.vfs.NamedContainerImpl;
import org.olat.core.util.vfs.VFSContainer;
import org.olat.core.util.vfs.VirtualContainer;
import org.olat.modules.curriculum.CurriculumService;
import org.olat.modules.curriculum.model.CurriculumElementWebDAVInfos;
import org.olat.repository.RepositoryEntry;
import org.olat.repository.RepositoryEntryStatusEnum;
import org.olat.repository.RepositoryManager;
import org.olat.repository.model.RepositoryEntryLifecycle;
/**
* This WebDAV provider delivery all folders in courses where the user
* is owner or is editor via a right group.
*
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*/
class CoursefolderWebDAVMergeSource extends WebDAVMergeSource {
private final IdentityEnvironment identityEnv;
private final WebDAVModule webDAVModule;
private final RepositoryManager repositoryManager;
private final CurriculumService curriculumService;
public CoursefolderWebDAVMergeSource(IdentityEnvironment identityEnv) {
super(identityEnv.getIdentity());
this.identityEnv = identityEnv;
webDAVModule = CoreSpringFactory.getImpl(WebDAVModule.class);
repositoryManager = CoreSpringFactory.getImpl(RepositoryManager.class);
curriculumService = CoreSpringFactory.getImpl(CurriculumService.class);
}
/*
* _others
* _managed
* _closed
* _manually
* _closed
*
* (non-Javadoc)
* @see org.olat.core.commons.services.webdav.manager.WebDAVMergeSource#loadMergedContainers()
*/
@Override
protected List<VFSContainer> loadMergedContainers() {
List<VFSContainer> containers = new ArrayList<>();
Map<String, VFSContainer> terms = new HashMap<>();
boolean useSemestersTerms = webDAVModule.isTermsFoldersEnabled();
boolean useCurriculumElementsTerms = webDAVModule.isCurriculumElementFoldersEnabled();
boolean prependReference = webDAVModule.isPrependCourseReferenceToTitle();
boolean useManaged = webDAVModule.isManagedFoldersEnabled();
NamingAndGrouping namingAndGrouping = new NamingAndGrouping(prependReference, useManaged, useSemestersTerms, useCurriculumElementsTerms);
if(useCurriculumElementsTerms) {
namingAndGrouping.setCurriculumElementInfos(getCurriculumElementWebDAVInfosMap());
}
NoTermContainer noTermContainer = new NoTermContainer(namingAndGrouping);
List<RepositoryEntry> editorEntries = repositoryManager.queryByOwner(getIdentity(), true, "CourseModule");
appendCourses(editorEntries, containers, terms, noTermContainer, namingAndGrouping, true);

srosse
committed
//add courses as participant and coaches
if(webDAVModule.isEnableLearnersParticipatingCourses()) {

srosse
committed
List<RepositoryEntry> entries = repositoryManager.getLearningResourcesAsParticipantAndCoach(getIdentity(), "CourseModule");
appendCourses(entries, containers, terms, noTermContainer, namingAndGrouping, false);
}
//add bookmarked courses
if(webDAVModule.isEnableLearnersBookmarksCourse()) {
List<RepositoryEntry> bookmarkedEntries = repositoryManager.getLearningResourcesAsBookmark(getIdentity(), identityEnv.getRoles(), "CourseModule", 0, -1);
appendCourses(bookmarkedEntries, containers, terms, noTermContainer, namingAndGrouping, false);
if (useSemestersTerms || useCurriculumElementsTerms) {
// add no-terms folder if any have been found
if (noTermContainer.hasNoTerms()) {
addContainerToList(noTermContainer.computeNoTermContainer(), containers);
} else if(noTermContainer.hasFinished()) {
addContainerToList(noTermContainer.getFinishedContainer(), containers);
}
return containers;
}
private Map<Long,List<CurriculumElementWebDAVInfos>> getCurriculumElementWebDAVInfosMap() {
List<CurriculumElementWebDAVInfos> infos = curriculumService.getCurriculumElementInfosForWebDAV(getIdentity());
Map<Long,List<CurriculumElementWebDAVInfos>> infoMap = new HashMap<>();
for(CurriculumElementWebDAVInfos info:infos) {
List<CurriculumElementWebDAVInfos> repoInfos = infoMap
.computeIfAbsent(info.getRepositoryEntryKey(), i -> new ArrayList<>());
if(!repoInfos.contains(info)) {
repoInfos.add(info);
}
}
return infoMap;
}
private void appendCourses(List<RepositoryEntry> courseEntries, List<VFSContainer> containers,
Map<String, VFSContainer> terms, NoTermContainer noTermContainer,
NamingAndGrouping namingAndGrouping, boolean editor) {
// Add all found repo entries to merge source
int count = 0;
for (RepositoryEntry re:courseEntries) {
if(namingAndGrouping.isDuplicate(re)) {
if(namingAndGrouping.isUseFinished() && re.getEntryStatus() == RepositoryEntryStatusEnum.closed) {
String courseTitle = getCourseTitle(re, namingAndGrouping.isPrependReference());
String name = namingAndGrouping.getFinishedUniqueName(courseTitle);
NamedContainerImpl cfContainer = new CoursefolderWebDAVNamedContainer(name, re, editor ? null : identityEnv);
noTermContainer.addToFinished(cfContainer);
} else if (namingAndGrouping.isUseSemesterTerms() || namingAndGrouping.isUseCurriculumElementsTerms()) {
appendCoursesWithTerms(re, containers, noTermContainer, terms, namingAndGrouping, editor);
String courseTitle = getCourseTitle(re, namingAndGrouping.isPrependReference());
String name = namingAndGrouping.getContainersUniqueName(courseTitle);
NamedContainerImpl cfContainer = new CoursefolderWebDAVNamedContainer(name, re, editor ? null : identityEnv);
addContainerToList(cfContainer, containers);
if(++count % 5 == 0) {
DBFactory.getInstance().commitAndCloseSession();
}
}
}
private void appendCoursesWithTerms(RepositoryEntry re, List<VFSContainer> containers, NoTermContainer noTermContainer,
Map<String, VFSContainer> terms, NamingAndGrouping namingAndGrouping, boolean editor) {
RepositoryEntryLifecycle lc = re.getLifecycle();
boolean termed = false;
if (namingAndGrouping.isUseSemesterTerms() && lc != null && !lc.isPrivateCycle()) {
// when a semester term info is found, add it to corresponding term folder
String termSoftKey = lc.getSoftKey();
VFSContainer termContainer = terms.computeIfAbsent(termSoftKey, term -> {
String normalizedKey = RequestUtil.normalizeFilename(term);
VirtualContainer container = new VirtualContainer(normalizedKey);
addContainerToList(container, containers);
return container;
});
String courseTitle = getCourseTitle(re, namingAndGrouping.isPrependReference());
String name = namingAndGrouping.getTermUniqueName(termSoftKey, courseTitle);
NamedContainerImpl cfContainer = new CoursefolderWebDAVNamedContainer(name, re, editor ? null : identityEnv);
termContainer.getItems().add(cfContainer);
termed = true;
}
if(namingAndGrouping.isUseManaged() && re.getEntryStatus() == RepositoryEntryStatusEnum.closed) {
String courseTitle = getCourseTitle(re, namingAndGrouping.isPrependReference());
String name = namingAndGrouping.getNoTermUniqueName(courseTitle);
NamedContainerImpl cfContainer = new CoursefolderWebDAVNamedContainer(name, re, editor ? null : identityEnv);
noTermContainer.add(re, cfContainer);
termed = true;
} else if(namingAndGrouping.isUseCurriculumElementsTerms() && namingAndGrouping.hasCurriculumElements(re)) {
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
List<CurriculumElementWebDAVInfos> elements = namingAndGrouping.getCurriculumElementInfos().get(re.getKey());
for(CurriculumElementWebDAVInfos element:elements) {
String termSoftKey = getTermSoftKey(element);
VFSContainer termContainer = terms.computeIfAbsent(termSoftKey, term -> {
String normalizedKey = RequestUtil.normalizeFilename(term);
VirtualContainer container = new VirtualContainer(normalizedKey);
addContainerToList(container, containers);
return container;
});
String courseTitle = getCourseTitle(re, false);
String name = namingAndGrouping.getTermUniqueName(termSoftKey, courseTitle);
NamedContainerImpl cfContainer = new CoursefolderWebDAVNamedContainer(name, re, editor ? null : identityEnv);
termContainer.getItems().add(cfContainer);
termed = true;
}
}
if(!termed) {
// no semester term found, add to no-term folder
String courseTitle = getCourseTitle(re, namingAndGrouping.isPrependReference());
String name = namingAndGrouping.getNoTermUniqueName(courseTitle);
NamedContainerImpl cfContainer = new CoursefolderWebDAVNamedContainer(name, re, editor ? null : identityEnv);
noTermContainer.add(re, cfContainer);
}
}
private String getCourseTitle(RepositoryEntry re, boolean prependReference) {
String displayName = re.getDisplayname();
if(prependReference && StringHelper.containsNonWhitespace(re.getExternalRef())) {
displayName = re.getExternalRef() + " " + displayName;
}
return RequestUtil.normalizeFilename(displayName);
}
private String getTermSoftKey(CurriculumElementWebDAVInfos element) {
StringBuilder sb = new StringBuilder(64);
if(StringHelper.containsNonWhitespace(element.getParentCurriculumElementDisplayName())) {
if(StringHelper.containsNonWhitespace(element.getParentCurriculumElementIdentifier())) {
sb.append(element.getParentCurriculumElementIdentifier()).append(" ");
}
sb.append(element.getParentCurriculumElementDisplayName());
} else if(StringHelper.containsNonWhitespace(element.getCurriculumElementDisplayName())) {
if(StringHelper.containsNonWhitespace(element.getCurriculumElementIdentifier())) {
sb.append(element.getCurriculumElementIdentifier()).append(" ");
}
sb.append(element.getCurriculumElementDisplayName());
}
return sb.toString();
}
private static class NoTermContainer {
private final Set<RepositoryEntry> entriesSet = new HashSet<>();
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
private final VirtualContainer noTermContainer = new VirtualContainer("_other");
private final VirtualContainer finishedContainer = new VirtualContainer("_finished");
private VirtualContainer managedContainer;
private VirtualContainer managedAndClosedContainer;
private VirtualContainer manuallyContainer;
private VirtualContainer manuallyAndClosedContainer;
private final NamingAndGrouping namingAndGrouping;
public NoTermContainer(NamingAndGrouping namingAndGrouping) {
this.namingAndGrouping = namingAndGrouping;
}
public boolean hasNoTerms() {
return !noTermContainer.getItems().isEmpty();
}
public VFSContainer computeNoTermContainer() {
return noTermContainer;
}
public boolean hasFinished() {
return !finishedContainer.getItems().isEmpty();
}
public VFSContainer getFinishedContainer() {
return finishedContainer;
}
public void addToFinished(VFSContainer container) {
finishedContainer.getItems().add(container);
}
public void addToManagedAndClosed(VFSContainer container) {
if(managedAndClosedContainer == null) {
managedAndClosedContainer = new VirtualContainer("_closed");
addToManaged(managedAndClosedContainer);
}
managedAndClosedContainer.getItems().add(container);
}
public void addToManaged(VFSContainer container) {
if(managedContainer == null) {
managedContainer = new VirtualContainer("_managed");
noTermContainer.getItems().add(managedContainer);
}
managedContainer.getItems().add(container);
}
public void addToManuualyAndClosed(VFSContainer container) {
if(manuallyAndClosedContainer == null) {
manuallyAndClosedContainer = new VirtualContainer("_closed");
addToManually(manuallyAndClosedContainer);
}
manuallyAndClosedContainer.getItems().add(container);
}
public void addToManually(VFSContainer container) {
if(manuallyContainer == null) {
manuallyContainer = new VirtualContainer("_manually");
noTermContainer.getItems().add(manuallyContainer);
}
manuallyContainer.getItems().add(container);
}
public void add(RepositoryEntry entry, VFSContainer container) {
if(entriesSet.contains(entry)) {
return;
} else {
entriesSet.add(entry);
}
if(namingAndGrouping.isUseManaged()) {
if(StringHelper.containsNonWhitespace(entry.getManagedFlagsString())) {
if(entry.getEntryStatus() == RepositoryEntryStatusEnum.closed) {
addToManagedAndClosed(container);
} else {
addToManaged(container);
}
} else if(entry.getEntryStatus() == RepositoryEntryStatusEnum.closed) {
addToManuualyAndClosed(container);
} else {
addToManually(container);
}
} else {
noTermContainer.getItems().add(container);
}
}
}
private static class NamingAndGrouping {
private final boolean useManaged;
private final boolean prependReference;
private final boolean useSemesterTerms;
private final boolean useCurriculumElementsTerms;
private final Set<RepositoryEntry> duplicates = new HashSet<>();
private final Set<String> containers = new HashSet<>();
private final Set<String> noTermContainer = new HashSet<>();
private final Set<String> finishedContainer = new HashSet<>();
private final Map<String,Set<String>> termContainers = new HashMap<>();
private Map<Long,List<CurriculumElementWebDAVInfos>> curriculumElementInfos;
public NamingAndGrouping(boolean prependReference, boolean useManaged,
boolean useSemesterTerms, boolean useCurriculumElementsTerms) {
this.prependReference = prependReference;
this.useManaged = useManaged;
this.useSemesterTerms = useSemesterTerms;
this.useCurriculumElementsTerms = useCurriculumElementsTerms;
}
public boolean isUseManaged() {
return useManaged;
}
public boolean isUseSemesterTerms() {
return useSemesterTerms;
}
public boolean isUseCurriculumElementsTerms() {
return useCurriculumElementsTerms;
}
public boolean isPrependReference() {
return prependReference;
}
public boolean isUseFinished() {
return !useSemesterTerms && !useSemesterTerms && !useManaged;
}
public Map<Long, List<CurriculumElementWebDAVInfos>> getCurriculumElementInfos() {
return curriculumElementInfos;
}
public void setCurriculumElementInfos(Map<Long, List<CurriculumElementWebDAVInfos>> curriculumElementInfos) {
this.curriculumElementInfos = curriculumElementInfos;
}
public boolean hasCurriculumElements(RepositoryEntry re) {
return curriculumElementInfos != null && curriculumElementInfos.containsKey(re.getKey());
}
public boolean isDuplicate(RepositoryEntry re) {
boolean duplicate = duplicates.contains(re);
if(!duplicate) {
duplicates.add(re);
}
return duplicate;
}
private String getTermUniqueName(String term, String courseTitle) {
String name = courseTitle;
if(termContainers.containsKey(term)) {
Set<String> termContainer = termContainers.get(term);
name = getUniqueName(courseTitle, termContainer);
} else {
Set<String> termContainer = new HashSet<>();
termContainer.add(courseTitle);
termContainers.put(term, termContainer);
}
return name;
}
private String getNoTermUniqueName(String courseTitle) {
return getUniqueName(courseTitle, noTermContainer);
}
private String getFinishedUniqueName(String courseTitle) {
return getUniqueName(courseTitle, finishedContainer);
}
private String getContainersUniqueName(String courseTitle) {
return getUniqueName(courseTitle, containers);
}
private String getUniqueName(String name, Set<String> set) {
String uniqueName = name;
if(set.contains(name)) {
// attach a serial to the group name to avoid duplicate mount points...
int serial = 1;
while (set.contains(name + " " + serial) && serial < 255) {
serial++;
}
uniqueName = name + " " + serial;
}
set.add(uniqueName);
return uniqueName;
}
}