/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <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>
* Copyright (c) 1999-2008 at frentix GmbH, Switzerland, http://www.frentix.com
* <p>
*/
package org.olat.modules.glossary;
import java.io.File;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import org.apache.lucene.document.Document;
import org.olat.core.commons.modules.bc.FolderConfig;
import org.olat.core.commons.modules.bc.vfs.OlatRootFolderImpl;
import org.olat.core.commons.modules.glossary.GlossaryItemManager;
import org.olat.core.commons.services.search.OlatDocument;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.media.CleanupAfterDeliveryFileMediaResource;
import org.olat.core.gui.media.MediaResource;
import org.olat.core.id.OLATResourceable;
import org.olat.core.util.ZipUtil;
import org.olat.core.util.filter.Filter;
import org.olat.core.util.filter.FilterFactory;
import org.olat.core.util.vfs.LocalFileImpl;
import org.olat.core.util.vfs.VFSContainer;
import org.olat.core.util.vfs.VFSItem;
import org.olat.core.util.vfs.VFSLeaf;
import org.olat.course.CourseFactory;
import org.olat.course.ICourse;
import org.olat.course.config.CourseConfig;
import org.olat.fileresource.FileResourceManager;
import org.olat.fileresource.types.GlossaryResource;
import org.olat.repository.RepositoryEntry;
import org.olat.repository.RepositoryEntryImportExport;
import org.olat.repository.RepositoryManager;
import org.olat.resource.OLATResource;
import org.olat.resource.OLATResourceImpl;
import org.olat.resource.OLATResourceManager;
import org.olat.resource.references.ReferenceImpl;
import org.olat.resource.references.ReferenceManager;
import org.olat.search.service.SearchResourceContext;
/**
* Description:<br>
* Manager to create, delete etc. glossary learning resources. The OLAT glossary
* functionality is based on the core framework glossary / textmarker functions.
* <P>
* <P>
* Initial Date: 15.01.2009 <br>
* @author Roman Haag, frentix GmbH, roman.haag@frentix.com
*/
public class GlossaryManagerImpl extends GlossaryManager {
private static final String EXPORT_FOLDER_NAME = "glossary";
public GlossaryManagerImpl(){
super();
}
/**
* Returns the internal glossary folder.
*
* @param res
* @return
*/
public OlatRootFolderImpl getGlossaryRootFolder(OLATResourceable res) {
OlatRootFolderImpl resRoot = FileResourceManager.getInstance().getFileResourceRootImpl(res);
if (resRoot == null) return null;
VFSItem glossaryRoot = resRoot.resolve(INTERNAL_FOLDER_NAME);
if (glossaryRoot == null) {
// Glossary has been imported but not yet renamed to the internal folder.
// This is ugly but no other way to do since the add resource callback
// somehow does not provide this hook?
VFSItem unzipped = resRoot.resolve(FileResourceManager.ZIPDIR);
if (unzipped == null) {
// Should not happen, but since we have no unzipped folder we better
// continue with an empty glossary than crashing
resRoot.createChildContainer(INTERNAL_FOLDER_NAME);
} else {
// We do not use the unzipped folder anymore, this was only for import.
// We rename it to the internal glossary folder and use it from now on
unzipped.rename(INTERNAL_FOLDER_NAME);
}
glossaryRoot = resRoot.resolve(INTERNAL_FOLDER_NAME);
}
return (OlatRootFolderImpl) glossaryRoot;
}
/**
* Creates a lucene index document for this glossary
*
* @param repositoryEntry
* @param searchResourceContext
* @return Document the index document
*/
public Document getIndexerDocument(RepositoryEntry repositoryEntry, SearchResourceContext searchResourceContext) {
GlossaryItemManager gIMgr = GlossaryItemManager.getInstance();
VFSContainer glossaryFolder = getGlossaryRootFolder(repositoryEntry.getOlatResource());
VFSLeaf glossaryFile = gIMgr.getGlossaryFile(glossaryFolder);
if (glossaryFile == null) { return null; }
String glossaryContent = gIMgr.getGlossaryContent(glossaryFolder);
// strip all html tags
Filter htmlTagsFilter = FilterFactory.getHtmlTagsFilter();
glossaryContent = htmlTagsFilter.filter(glossaryContent);
// create standard olat index document with this data
OlatDocument glossaryDocument = new OlatDocument();
if (repositoryEntry.getInitialAuthor() != null) {
glossaryDocument.setAuthor(repositoryEntry.getInitialAuthor());
}
if (repositoryEntry.getDisplayname() != null) {
glossaryDocument.setTitle(repositoryEntry.getDisplayname());
}
if (repositoryEntry.getDescription() != null) {
glossaryDocument.setDescription(htmlTagsFilter.filter(repositoryEntry.getDescription()));
}
glossaryDocument.setContent(glossaryContent);
glossaryDocument.setCreatedDate(repositoryEntry.getCreationDate());
glossaryDocument.setLastChange(new Date(glossaryFile.getLastModified()));
glossaryDocument.setResourceUrl(searchResourceContext.getResourceUrl());
glossaryDocument.setDocumentType(searchResourceContext.getDocumentType());
glossaryDocument.setCssIcon("o_FileResource-GLOSSARY_icon");
return glossaryDocument.getLuceneDocument();
}
/**
* Exports the glossary resource to the given export directory
*
* @param glossarySoftkey
* @param exportedDataDir
* @return
*/
public boolean exportGlossary(String glossarySoftkey, File exportedDataDir) {
RepositoryEntry re = RepositoryManager.getInstance().lookupRepositoryEntryBySoftkey(glossarySoftkey, false);
if (re == null) return false;
File fExportBaseDirectory = new File(exportedDataDir, EXPORT_FOLDER_NAME);
if (!fExportBaseDirectory.mkdir()) return false;
// export properties
RepositoryEntryImportExport reImportExport = new RepositoryEntryImportExport(re, fExportBaseDirectory);
return reImportExport.exportDoExport();
}
/**
* Export the glossary as a media resource. The resource name is set to the
* resources display name
*
* @param res
* @return
*/
public MediaResource getAsMediaResource(OLATResourceable res) {
RepositoryEntry repoEntry = RepositoryManager.getInstance().lookupRepositoryEntry(res, false);
String exportFileName = repoEntry.getDisplayname() + ".zip";
File fExportZIP = new File(FolderConfig.getCanonicalTmpDir() + "/" + exportFileName);
VFSContainer glossaryRoot = getGlossaryRootFolder(res);
ZipUtil.zip(glossaryRoot.getItems(), new LocalFileImpl(fExportZIP));
return new CleanupAfterDeliveryFileMediaResource(fExportZIP);
}
/**
* Creates a glossary resource and creates the necessary folders on disk. The
* glossary will be placed in the resources _unizipped dir to make import /
* export easier
*
* @return
*/
public GlossaryResource createGlossary() {
GlossaryResource resource = new GlossaryResource();
VFSContainer rootContainer = FileResourceManager.getInstance().getFileResourceRootImpl(resource);
if (rootContainer == null) return null;
if (rootContainer.createChildContainer(INTERNAL_FOLDER_NAME) == null) return null;
OLATResourceManager rm = OLATResourceManager.getInstance();
OLATResource ores = rm.createOLATResourceInstance(resource);
rm.saveOLATResource(ores);
return resource;
}
/**
* The import export data container used for course import
*
* @param importDataDir
* @return
*/
public RepositoryEntryImportExport getRepositoryImportExport(File importDataDir) {
File fImportBaseDirectory = new File(importDataDir, EXPORT_FOLDER_NAME);
return new RepositoryEntryImportExport(fImportBaseDirectory);
}
//TODO:RH:gloss change courseconfig, to keep more than 1 single glossary as a list
/**
* @param res glossary to be deleted
*/
public void deleteGlossary(OLATResourceable res) {
// first remove all references
ReferenceManager refM = ReferenceManager.getInstance();
List repoRefs = refM.getReferencesTo(res);
for (Iterator iter = repoRefs.iterator(); iter.hasNext();) {
ReferenceImpl ref = (ReferenceImpl) iter.next();
if (ref.getUserdata().equals(GLOSSARY_REPO_REF_IDENTIFYER)) {
// remove the reference from the course configuration
// TODO:RH:improvement: this should use a callback method or send a general delete
// event so that the course can take care of this rather than having it
// here hardcoded
OLATResourceImpl courseResource = ref.getSource();
//ICourse course = CourseFactory.loadCourse(courseResource);
ICourse course = CourseFactory.openCourseEditSession(courseResource.getResourceableId());
CourseConfig cc = course.getCourseEnvironment().getCourseConfig();
cc.setGlossarySoftKey(null);
CourseFactory.setCourseConfig(course.getResourceableId(), cc);
CourseFactory.closeCourseEditSession(course.getResourceableId(),true);
// remove reference from the references table
refM.delete(ref);
}
}
// now remove the resource itself
FileResourceManager.getInstance().deleteFileResource(res);
}
/**
* Creates a copy of a glossary
*
* @param res
* @param ureq
* @return the copy
*/
public OLATResourceable createCopy(OLATResourceable res, UserRequest ureq) {
FileResourceManager frm = FileResourceManager.getInstance();
OLATResourceable copy = frm.createCopy(res, INTERNAL_FOLDER_NAME);
return copy;
}
public String archive(String archivFilePath, RepositoryEntry repoEntry) {
String exportFileName = "del_glossar_" + repoEntry.getOlatResource().getResourceableId() + ".zip";
String fullFilePath = archivFilePath + File.separator + exportFileName;
File fExportZIP = new File(fullFilePath);
VFSContainer glossaryRoot = getGlossaryRootFolder(repoEntry.getOlatResource());
ZipUtil.zip(glossaryRoot.getItems(), new LocalFileImpl(fExportZIP));
return fullFilePath;
}
}