/**
* 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) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <hr>
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* This file has been modified by the OpenOLAT community. Changes are licensed
* under the Apache 2.0 license as the original file.
*/
package org.olat.modules.wiki;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import org.jamwiki.parser.ParserDocument;
import org.jamwiki.parser.ParserInput;
import org.jamwiki.parser.jflex.JFlexParser;
import org.olat.core.CoreSpringFactory;
import org.olat.core.gui.translator.Translator;
import org.olat.core.id.Identity;
import org.olat.core.id.OLATResourceable;
import org.olat.core.id.UserConstants;
import org.olat.core.logging.OLATRuntimeException;
import org.olat.core.util.Formatter;
import org.olat.group.BusinessGroup;
import org.olat.group.BusinessGroupService;
import org.olat.ims.cp.CPCore;
import org.olat.modules.wiki.gui.components.wikiToHtml.StaticExportWikiDataHandler;
import org.olat.repository.RepositoryEntry;
import org.olat.repository.RepositoryManager;
/**
* Description:<br>
* To generate an snapshot of the current wiki users can export it in an
* offlinereadeble html export. The export contains also an IMS content package
* manifest and therefore can be reimported as an static html content which is
* no longer editable back into OLAT or any other IMS CP capable LMS.
* <P>
* Initial Date: Aug 7, 2006 <br>
*
* @author guido
*/
public class WikiToCPExport {
public static final String WIKI_MANIFEST_IDENTIFIER = "wiki_cp_export_v1";
private final OLATResourceable ores;
private final Translator trans;
private final JFlexParser parser;
/**
*
* @param ores the repositoryEntry of the wiki OR the businessGroup, if the wiki is in a group
* @param ident
* @param trans
*/
public WikiToCPExport(OLATResourceable ores, Translator trans) {
this.ores = ores;
this.trans = trans;
StaticExportWikiDataHandler datahandler = new StaticExportWikiDataHandler();
datahandler.setWiki(ores);
ParserInput parserInput = new ParserInput();
parserInput.setWikiUser(null);
parserInput.setAllowSectionEdit(false);
parserInput.setDepth(10);
parserInput.setContext("");
// input.setTableOfContents(null);
parserInput.setLocale(new Locale("en"));
parserInput.setVirtualWiki("");
parserInput.setTopicName("dummy");
parserInput.setUserIpAddress("0.0.0.0");
parserInput.setDataHandler(datahandler);
parser = new JFlexParser(parserInput);
}
protected String createJsMappingContent(Wiki wiki) {
StringBuilder sb = new StringBuilder();
List<WikiPage> pages = wiki.getPagesByDate();
// create javascript assoz. array
sb.append("var mappings = new Array();\n");
for (final Iterator<WikiPage> iter = pages.iterator(); iter.hasNext();) {
final WikiPage page = iter.next();
sb.append("mappings[\"").append(page.getPageName().replace("&", "%26").toLowerCase(Locale.ENGLISH)).append("\"] = ");
sb.append("\"").append(page.getPageId()).append(".html\"\n");
}
// create function
sb.append("function mapLinks() {");
sb.append("var anchors = document.getElementsByTagName(\"a\");");
sb.append("for (var i=0; i<anchors.length; i++) {");
sb.append("var anchor = anchors[i];");
sb.append("var href = anchor.getAttribute(\"href\");");
sb.append("if (href && href.indexOf(\"//Media\") >= 0) { anchor.setAttribute(\"href\", href.substr(8)); }");
sb.append("else if (href && href.substr(0,2).indexOf(\"//\") != -1) {");
sb.append("anchor.setAttribute(\"href\", mappings[decodeURI(href.substr(2)).toLowerCase()]);");
sb.append("}");
sb.append("}");
sb.append("}");
sb.append("window.onload = mapLinks;");
return sb.toString();
}
protected String createIMSManifest(Wiki wiki, Identity ident) {
StringBuilder sb = new StringBuilder();
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
sb.append("<manifest xmlns=\"http://www.imsglobal.org/xsd/imscp_v1p1\" " + "xmlns:imsmd=\"http://www.imsglobal.org/xsd/imsmd_v1p2\" "
+ "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " + "identifier=\"");
sb.append(WIKI_MANIFEST_IDENTIFIER);
sb.append("\" xsi:schemaLocation=\"http://www.imsglobal.org/xsd/imscp_v1p1 imscp_v1p1.xsd "
+ "http://www.imsglobal.org/xsd/imsmd_v1p2 imsmd_v1p2p2.xsd\">");
sb.append("<metadata><imsmd:lom><imsmd:general>");
sb.append("<imsmd:identifier></imsmd:identifier>");
sb.append("<imsmd:title><imsmd:langstring xml:lang=\"de\">");
sb.append("");
sb.append("</imsmd:langstring></imsmd:title>");
sb.append("<imsmd:language>de</imsmd:language>");
sb.append("<imsmd:description><imsmd:langstring xml:lang=\"de\">");
sb.append("Exported wiki from the OLAT Learning Management System");
sb.append("</imsmd:langstring></imsmd:description>");
sb.append("<imsmd:keyword><imsmd:langstring xml:lang=\"de\">OLAT Wiki export</imsmd:langstring></imsmd:keyword>");
sb.append("</imsmd:general>");
sb.append("<imsmd:lifecycle>");
sb.append("<imsmd:version><imsmd:langstring xml:lang=\"de\">1.0</imsmd:langstring></imsmd:version>");
sb.append("<imsmd:status>");
sb.append("<imsmd:source><imsmd:langstring xml:lang=\"x-none\">LOMv1.0</imsmd:langstring></imsmd:source>");
sb.append("<imsmd:value><imsmd:langstring xml:lang=\"x-none\">Draft</imsmd:langstring></imsmd:value>");
sb.append("</imsmd:status>");
sb.append("<imsmd:contribute>");
sb.append("<imsmd:role>");
sb.append("<imsmd:source><imsmd:langstring xml:lang=\"x-none\">LOMv1.0</imsmd:langstring></imsmd:source>");
sb.append("<imsmd:value><imsmd:langstring xml:lang=\"x-none\">Author</imsmd:langstring></imsmd:value>");
sb.append("</imsmd:role>");
sb.append("<imsmd:centity><imsmd:vcard>");
sb.append(ident.getUser().getProperty(UserConstants.FIRSTNAME, trans.getLocale())).append(" ")
.append(ident.getUser().getProperty(UserConstants.LASTNAME, trans.getLocale()));
sb.append("</imsmd:vcard></imsmd:centity>");
sb.append("<imsmd:date><imsmd:datetime>");
sb.append(Formatter.formatDatetime(new Date(System.currentTimeMillis())));
sb.append("</imsmd:datetime></imsmd:date>");
sb.append("</imsmd:contribute>");
sb.append("</imsmd:lifecycle>");
sb.append("<imsmd:technical><imsmd:format>text/html</imsmd:format></imsmd:technical>");
sb.append("</imsmd:lom></metadata>");
sb.append("<organizations default=\"");
sb.append(CPCore.OLAT_ORGANIZATION_IDENTIFIER);
sb.append("\">");
sb.append("<organization identifier=\"");
sb.append(CPCore.OLAT_ORGANIZATION_IDENTIFIER);
sb.append("\" structure=\"hierarchical\">");
sb.append("<title>");
String name = "";
if (WikiManager.getInstance().isGroupContextWiki(ores)) {
BusinessGroup group = CoreSpringFactory.getImpl(BusinessGroupService.class).loadBusinessGroup(ores.getResourceableId());
name = group.getName();
sb.append(trans.translate("wiki.exported.from.group", new String[] { name }));
} else {
if(ores instanceof RepositoryEntry){
name = ((RepositoryEntry)ores).getDisplayname();
}else{
RepositoryEntry entry = RepositoryManager.getInstance().lookupRepositoryEntry(ores, true);
name = entry.getDisplayname();
}
sb.append(trans.translate("wiki.exported.from.repository", new String[] { name }));
}
sb.append("</title>");
createItems(sb, wiki);
sb.append("</organization></organizations>");
sb.append("<resources>");
createResources(sb, wiki);
sb.append("</resources>");
sb.append("</manifest>"); // close manifest
return sb.toString();
}
private void createItems(StringBuilder sb, Wiki wiki) {
// <item identifier="ITEM-Einleitung" identifierref="Resource-Einleitung"
// isvisible="true">
// <title>Einleitung</title>
// </item>
List<WikiPage> topLevelPages = new ArrayList<WikiPage>();
topLevelPages.add(wiki.getPage(WikiPage.WIKI_INDEX_PAGE));
WikiPage pageAtoZ = wiki.getPage(WikiPage.WIKI_A2Z_PAGE);
pageAtoZ.setContent(wiki.getAllPageNamesSorted());
topLevelPages.add(pageAtoZ);
topLevelPages.add(wiki.getPage(WikiPage.WIKI_MENU_PAGE));
for (WikiPage page : topLevelPages) {
sb.append(openingItemTag(page));
sb.append(titleTag(page));
// If the page is the a-z page, append all pages as subitems
if (page.getPageName().equals(WikiPage.WIKI_A2Z_PAGE)) {
List<WikiPage> allPages = wiki.getAllPagesWithContent();
Collections.sort(allPages, new WikiPageComparator());
// remove all toplevel pages, otherwise we would get duplicate
// identifiers
allPages.removeAll(topLevelPages);
for (WikiPage subPage : allPages) {
sb.append(openingItemTag(subPage));
sb.append(titleTag(subPage));
sb.append(closingItemTag());
// }
}
}
sb.append(closingItemTag());
}
}
/**
* @param page
* @return opening item tag
*/
private StringBuffer openingItemTag(WikiPage page) {
StringBuffer sb = new StringBuffer();
sb.append("<item identifier=\"").append(page.getPageId()).append("\" ").append("identifierref=\"res_");
sb.append(page.getPageId()).append("\" isvisible=\"true\">");
return sb;
}
/**
* @return closing item tag
*/
private String closingItemTag() {
return "</item>";
}
/**
* @param page
* @return entire title tag
*/
private StringBuffer titleTag(WikiPage page) {
StringBuffer sb = new StringBuffer();
sb.append("<title>");
if (page.getPageName().equals(WikiPage.WIKI_A2Z_PAGE)) sb.append(trans.translate("navigation.a-z"));
else if (page.getPageName().equals(WikiPage.WIKI_MENU_PAGE)) sb.append(trans.translate("navigation.menu"));
else if (page.getPageName().equals(WikiPage.WIKI_INDEX_PAGE)) sb.append(trans.translate("navigation.mainpage"));
else sb.append("<![CDATA[" + page.getPageName() + "]]>");
sb.append("</title>");
return sb;
}
private void createResources(StringBuilder sb, Wiki wiki) {
// <resource identifier="Resource-Einleitung" type="text/html"
// href="einleitung.html">
// <file href="einleitung.html" />
// </resource>
List<WikiPage> pageNames = wiki.getPagesByDate();
for (WikiPage page :pageNames) {
sb.append("<resource identifier=\"res_").append(page.getPageId()).append("\" type=\"text/html\" ").append("href=\"");
sb.append(page.getPageId()).append(".html\">");
sb.append("<file href=\"").append(page.getPageId()).append(".html\" />");
sb.append("</resource>");
}
}
protected String wikiPageToHtml(WikiPage page) {
StringBuilder sb = new StringBuilder();
sb.append("<html>");
sb.append("<head>\n");
sb.append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n");
sb.append("<style type=\"text/css\">img {float:right;padding:10px;}</style>\n");
//sb.append("<script type=\"text/javascript\" src=\"cp_offline_menu_mat/jsMath/easy/load.js\"></script>\n");
sb.append("<script type=\"text/javascript\" src=\"cp_offline_menu_mat/wiki.js\"></script>\n");
sb.append("<script type=\"text/javascript\" src=\"mapping.js\"></script>\n");
sb.append("<link rel=\"StyleSheet\" href=\"cp_offline_menu_mat/wiki.css\" type=\"text/css\" media=\"screen, print\">\n");
sb.append("</head>\n");
sb.append("<body>\n");
sb.append("<h3>").append(getTranslatedWikiPageName(page)).append("</h3>");
sb.append("<hr><div id=\"olat-wiki\">");
try {
ParserDocument doc = parser.parseHTML(page.getContent());
sb.append(doc.getContent());
} catch (Exception e) {
throw new OLATRuntimeException("error while parsing from wiki to CP. ores:" + ores.getResourceableId(), e);
}
sb.append("</div></body></html>");
return sb.toString();
}
/**
* returns the translated wikiPage-name if given page is special (A-Z or the
* wiki Menu). Otherwise returns the title of the given wiki page
*
* @param page
* @return
*/
private String getTranslatedWikiPageName(WikiPage page){
if (page.getPageName().equals(WikiPage.WIKI_A2Z_PAGE)) {
return trans.translate("navigation.a-z");
} else if (page.getPageName().equals(WikiPage.WIKI_MENU_PAGE)) {
return trans.translate("navigation.menu");
} else {
return page.getPageName();
}
}
}