From 2b8f2308fdce25dc12a256eb23043706db9afdfc Mon Sep 17 00:00:00 2001 From: srosse <none@none> Date: Thu, 18 Apr 2013 15:27:11 +0200 Subject: [PATCH] OO-533: export/import with materials, fix small issues and wording --- .../chiefcontrollers/_content/body.html | 13 +- .../simple/SimpleBaseController.java | 2 +- .../form/flexible/FormUIFactory.java | 6 +- .../flexible/impl/FormBasicController.java | 3 +- .../richText/RichTextConfiguration.java | 9 +- .../IMS_CP_Editor_Stand_der_Dinge_jan09_.pdf | Bin 60538 -> 0 bytes .../qti/editor/QTIEditorMainController.java | 11 +- .../ims/qti/qpool/QTIExportProcessor.java | 277 ++++++++++++++++-- .../ims/qti/qpool/QTIImportProcessor.java | 10 +- .../qti/qpool/QTIQPoolServiceProvider.java | 26 +- .../java/org/olat/modules/qpool/QPoolSPI.java | 6 +- .../org/olat/modules/qpool/QPoolService.java | 11 +- .../manager/AbstractExportTestResource.java | 2 + .../manager/AbstractQPoolServiceProvider.java | 3 +- .../qpool/manager/ExportQItemResource.java | 7 +- .../manager/ExportQItemsZipResource.java | 111 +++++++ ...rter.java => MetadataConverterHelper.java} | 88 ++++-- .../modules/qpool/manager/QItemTypeDAO.java | 9 + .../manager/QuestionPoolServiceImpl.java | 35 ++- .../modules/qpool/ui/ImportController.java | 12 + .../ui/QuestionItemPreviewController.java | 31 +- .../ui/QuestionItemSummaryController.java | 52 ++-- .../ui/QuestionPoolMainEditorController.java | 12 +- .../modules/qpool/ui/QuestionsController.java | 4 +- .../qpool/ui/_i18n/LocalStrings_de.properties | 15 +- .../ui/admin/QItemTypesAdminController.java | 8 +- .../ui/admin/_i18n/LocalStrings_de.properties | 6 +- .../edit/EducationalMetadataController.java | 6 +- .../EducationalMetadataEditController.java | 12 +- .../edit/LifecycleMetadataEditController.java | 5 +- .../ui/edit/QuestionMetadataController.java | 6 +- .../edit/QuestionMetadataEditController.java | 34 ++- .../edit/TechnicalMetadataEditController.java | 6 +- .../wizard/_i18n/LocalStrings_de.properties | 4 +- src/main/webapp/static/js/functions.js | 16 +- src/main/webapp/static/js/js.plugins.min.js | 2 +- .../olatmovieviewer/olatmovieviewer.htm | 13 +- ....java => MetadataConverterHelperTest.java} | 51 ++-- .../java/org/olat/test/AllTestsJunit4.java | 2 +- 39 files changed, 729 insertions(+), 197 deletions(-) delete mode 100644 src/main/java/org/olat/ims/cp/IMS_CP_Editor_Stand_der_Dinge_jan09_.pdf create mode 100644 src/main/java/org/olat/modules/qpool/manager/ExportQItemsZipResource.java rename src/main/java/org/olat/modules/qpool/manager/{LOMConverter.java => MetadataConverterHelper.java} (82%) rename src/test/java/org/olat/modules/qpool/manager/{LOMConverterTest.java => MetadataConverterHelperTest.java} (68%) diff --git a/src/main/java/org/olat/core/commons/chiefcontrollers/_content/body.html b/src/main/java/org/olat/core/commons/chiefcontrollers/_content/body.html index 38471a06aa1..1a8f82da956 100644 --- a/src/main/java/org/olat/core/commons/chiefcontrollers/_content/body.html +++ b/src/main/java/org/olat/core/commons/chiefcontrollers/_content/body.html @@ -53,26 +53,20 @@ function b_start(){ <script type="text/javascript" src='$r.staticLink("js/modernizr/modernizr.js")'></script> ## jQuery libraries <script type="text/javascript" src='$r.staticLink("js/jquery/jquery-1.9.1.min.js")'></script> -<script> -/* <![CDATA[ */ - jQuery.noConflict(); -/* ]]> */ -</script> <script type="text/javascript" src='$r.staticLink("js/jquery/jquery-migrate-1.1.1.min.js")'></script> <script type="text/javascript" src='$r.staticLink("js/jquery/ui/jquery-ui-1.10.2.custom.min.js")'></script> -<!-- can be compressed jquery.all.plugins.min.js --> +## Are compressed as js/js.plugins.min.js ## <script type="text/javascript" src='$r.staticLink("js/jquery/periodic/jquery.periodic.js")'></script> ## <script type="text/javascript" src='$r.staticLink("js/jshashtable-2.1_src.js")'></script> ## <script type="text/javascript" src='$r.staticLink("js/jquery/openolat/jquery.oolog.js")'></script> ## <script type="text/javascript" src='$r.staticLink("js/jquery/openolat/jquery.translator.js")'></script> ## <script type="text/javascript" src='$r.staticLink("js/functions.js")'></script> <script type="text/javascript" src='$r.staticLink("js/js.plugins.min.js")'></script> - <script type="text/javascript" src='$r.staticLink("movie/player.js")'></script> <script type="text/javascript" src='$r.staticLink("js/jsMath/easy/load.js")'></script> -<!-- loaded always --> +## Always loaded ## <link type="text/css" href='$r.staticLink("js/jquery/tagit/jquery.tagit.css")' rel="stylesheet"/> ## <link type="text/css" href='$r.staticLink("js/jquery/uilayout/layout-default-latest.css")' rel="stylesheet"/> ## <link type="text/css" href='$r.staticLink("js/jquery/fullcalendar/fullcalendar.css")' rel="stylesheet"/> @@ -82,6 +76,7 @@ function b_start(){ <script type="text/javascript"> /* <![CDATA[ */ + jQuery.noConflict(); ## references to objects for later access or cleanup o_info.objectMap = new Hashtable(); ## Initialize js translator factory with the js translator mapper path @@ -90,8 +85,6 @@ function b_start(){ /* ]]> */ </script> - -## ## LAYOUT ## 1) Dynamic component CSS included by components $r.render("jsCssRawHtmlHeader", "pre-theme") diff --git a/src/main/java/org/olat/core/commons/chiefcontrollers/controller/simple/SimpleBaseController.java b/src/main/java/org/olat/core/commons/chiefcontrollers/controller/simple/SimpleBaseController.java index eec77a9f0d3..1b7cf726e57 100644 --- a/src/main/java/org/olat/core/commons/chiefcontrollers/controller/simple/SimpleBaseController.java +++ b/src/main/java/org/olat/core/commons/chiefcontrollers/controller/simple/SimpleBaseController.java @@ -78,7 +78,7 @@ public class SimpleBaseController extends BasicController implements Contentable guiMessage = new GUIMessage(); guimsgVc.contextPut("guiMessage", guiMessage); - guimsgPanel = new OncePanel("guimsgPanel"); + guimsgPanel = new OncePanel("simpleGuimsgPanel"); mainVc.put("guimessage", guimsgPanel); diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/FormUIFactory.java b/src/main/java/org/olat/core/gui/components/form/flexible/FormUIFactory.java index d293eb25995..825c52fec08 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/FormUIFactory.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/FormUIFactory.java @@ -573,7 +573,8 @@ public class FormUIFactory { */ public TextElement addTextElement(String name, final String i18nLabel, final int maxLen, String initialValue, FormItemContainer formLayout) { - return addTextElement(null, name, i18nLabel, maxLen, initialValue, formLayout); + String val = initialValue == null ? "" : initialValue; + return addTextElement(null, name, i18nLabel, maxLen, val, formLayout); } /** @@ -587,7 +588,8 @@ public class FormUIFactory { */ public TextElement addTextElement(String id, String name, final String i18nLabel, final int maxLen, String initialValue, FormItemContainer formLayout) { - TextElement te = new TextElementImpl(id, name, initialValue); + String val = initialValue == null ? "" : initialValue; + TextElement te = new TextElementImpl(id, name, val); te.setNotLongerThanCheck(maxLen, "text.element.error.notlongerthan"); setLabelIfNotNull(i18nLabel, te); te.setMaxLength(maxLen); diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/FormBasicController.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/FormBasicController.java index 9112a85ff04..f6e7ab9750e 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/FormBasicController.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/FormBasicController.java @@ -332,8 +332,7 @@ public abstract class FormBasicController extends BasicController { * evaluate normal inner form events */ FormItem fiSrc = fe.getFormItemSource(); - // check for InlineElments - //TODO jquery + // check for InlineElments remove as the tag library has been replaced /* if(fiSrc instanceof InlineElement){ if(!((InlineElement) fiSrc).isInlineEditingElement()){ //OO-137 diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextConfiguration.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextConfiguration.java index b52f4523fd7..bcacb0263c9 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextConfiguration.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextConfiguration.java @@ -390,8 +390,7 @@ public class RichTextConfiguration implements Disposable { plugins.add(SAFARI_PLUGIN); // Start observing of diry richt text element and trigger calling of setFlexiFormDirty() method // This check is initialized after the editor has fully loaded - //addOnInitCallbackFunction(ONINIT_CALLBACK_VALUE_START_DIRTY_OBSERVER + ".curry('" + rootFormDispatchId + "','" + domID + "')"); - addOnInitCallbackFunction(ONINIT_CALLBACK_VALUE_START_DIRTY_OBSERVER + "('" + rootFormDispatchId + "','" + domID + "')"); + addOnInitCallbackFunction(ONINIT_CALLBACK_VALUE_START_DIRTY_OBSERVER + ".curry('" + rootFormDispatchId + "','" + domID + "')"); } /** @@ -727,8 +726,7 @@ public class RichTextConfiguration implements Disposable { setQuotedConfigValue(THEME_ADVANCED_TOOLBAR_LOCATION, position); if (position.equals(THEME_ADVANCED_TOOLBAR_LOCATION_VALUE_EXTERNAL) && autoHide) { // set the on-init callback and add the auto-hide toolbar listener - //setNonQuotedConfigValue(INIT_INSTANCE_CALLBACK, INIT_INSTANCE_CALLBACK_VALUE_AUTO_HIDE_TOOLBAR + ".curry('" + domID + "')"); - setNonQuotedConfigValue(INIT_INSTANCE_CALLBACK, INIT_INSTANCE_CALLBACK_VALUE_AUTO_HIDE_TOOLBAR + "('" + domID + "')"); + setNonQuotedConfigValue(INIT_INSTANCE_CALLBACK, INIT_INSTANCE_CALLBACK_VALUE_AUTO_HIDE_TOOLBAR + ".curry('" + domID + "')"); } } else { throw new AssertException("Invalid configuration parameters, use RichTextConfigurationConstants"); @@ -1322,8 +1320,7 @@ public class RichTextConfiguration implements Disposable { */ public void setFileBrowserCallback(VFSContainer vfsContainer, CustomLinkTreeModel customLinkTreeModel, String[] supportedImageSuffixes, String[] supportedMediaSuffixes, String[] supportedFlashPlayerSuffixes) { // Add dom ID variable using prototype curry method - //TODO jquery setNonQuotedConfigValue(FILE_BROWSER_CALLBACK, FILE_BROWSER_CALLBACK_VALUE_LINK_BROWSER + ".curry('" + domID + "')"); - setNonQuotedConfigValue(FILE_BROWSER_CALLBACK, FILE_BROWSER_CALLBACK_VALUE_LINK_BROWSER + "('" + domID + "')"); + setNonQuotedConfigValue(FILE_BROWSER_CALLBACK, FILE_BROWSER_CALLBACK_VALUE_LINK_BROWSER + ".curry('" + domID + "')"); linkBrowserImageSuffixes = supportedImageSuffixes; linkBrowserMediaSuffixes = supportedMediaSuffixes; linkBrowserFlashPlayerSuffixes = supportedFlashPlayerSuffixes; diff --git a/src/main/java/org/olat/ims/cp/IMS_CP_Editor_Stand_der_Dinge_jan09_.pdf b/src/main/java/org/olat/ims/cp/IMS_CP_Editor_Stand_der_Dinge_jan09_.pdf deleted file mode 100644 index 645bab2b2064db5524881261e7f0de5416750285..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 60538 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ⅈ;7XIaiYVR^m`G8tc&l3DhH>@4b}i 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 bpE{MEUbY@y|J*JF28qBhi;1b|sxto%pFt== diff --git a/src/main/java/org/olat/ims/qti/editor/QTIEditorMainController.java b/src/main/java/org/olat/ims/qti/editor/QTIEditorMainController.java index 4a05601662b..64018bcf1fc 100644 --- a/src/main/java/org/olat/ims/qti/editor/QTIEditorMainController.java +++ b/src/main/java/org/olat/ims/qti/editor/QTIEditorMainController.java @@ -77,7 +77,7 @@ import org.olat.core.util.memento.Memento; import org.olat.core.util.nodes.INode; import org.olat.core.util.tree.TreeVisitor; import org.olat.core.util.tree.Visitor; -import org.olat.core.util.vfs.VFSLeaf; +import org.olat.core.util.vfs.VFSContainer; import org.olat.core.util.xml.XStreamHelper; import org.olat.course.CourseFactory; import org.olat.course.ICourse; @@ -110,7 +110,6 @@ import org.olat.modules.iq.IQDisplayController; import org.olat.modules.iq.IQManager; import org.olat.modules.iq.IQPreviewSecurityCallback; import org.olat.modules.qpool.QPoolService; -import org.olat.modules.qpool.QuestionItem; import org.olat.modules.qpool.QuestionItemView; import org.olat.modules.qpool.ui.QItemEvent; import org.olat.modules.qpool.ui.SelectItemController; @@ -907,9 +906,8 @@ public class QTIEditorMainController extends MainLayoutBasicController implement } private GenericQtiNode doConvertItemToQtiNode(QuestionItemView qitemv) { - QuestionItem qitem = qpoolService.loadItemById(qitemv.getKey()); - VFSLeaf leaf = qpoolService.getRootFile(qitem); - Item theItem = QTIEditHelper.readItemXml(leaf); + VFSContainer editorContainer = qtiPackage.getBaseDir(); + Item theItem = qtiQpoolServiceProvider.exportToQTIEditor(qitemv, editorContainer); GenericQtiNode node = new ItemNode(theItem, qtiPackage); return node; } @@ -933,7 +931,8 @@ public class QTIEditorMainController extends MainLayoutBasicController implement QTIObject qtiObject = itemNode.getUnderlyingQTIObject(); if(qtiObject instanceof Item) { Item item = (Item)qtiObject; - qtiQpoolServiceProvider.importBeecomItem(getIdentity(), item, getLocale()); + VFSContainer editorContainer = qtiPackage.getBaseDir(); + qtiQpoolServiceProvider.importBeecomItem(getIdentity(), item, editorContainer, getLocale()); showInfo("export.qpool.successful"); } } diff --git a/src/main/java/org/olat/ims/qti/qpool/QTIExportProcessor.java b/src/main/java/org/olat/ims/qti/qpool/QTIExportProcessor.java index 837da354c53..803f26dbff9 100644 --- a/src/main/java/org/olat/ims/qti/qpool/QTIExportProcessor.java +++ b/src/main/java/org/olat/ims/qti/qpool/QTIExportProcessor.java @@ -21,28 +21,43 @@ package org.olat.ims.qti.qpool; import java.io.IOException; import java.io.InputStream; +import java.io.StringReader; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; +import org.apache.commons.io.IOUtils; +import org.cyberneko.html.parsers.SAXParser; +import org.dom4j.Attribute; +import org.dom4j.CDATA; import org.dom4j.Document; import org.dom4j.DocumentFactory; import org.dom4j.Element; +import org.dom4j.Node; import org.dom4j.io.OutputFormat; import org.dom4j.io.XMLWriter; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.CodeHelper; +import org.olat.core.util.FileUtils; +import org.olat.core.util.StringHelper; import org.olat.core.util.ZipUtil; import org.olat.core.util.vfs.VFSContainer; import org.olat.core.util.vfs.VFSItem; import org.olat.core.util.vfs.VFSLeaf; +import org.olat.core.util.vfs.VFSManager; import org.olat.core.util.xml.XMLParser; import org.olat.ims.qti.QTIConstants; import org.olat.ims.resources.IMSEntityResolver; import org.olat.modules.qpool.QuestionItemFull; import org.olat.modules.qpool.manager.FileStorage; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.helpers.DefaultHandler; /** * @@ -60,54 +75,198 @@ public class QTIExportProcessor { this.qpoolFileStorage = qpoolFileStorage; } - public void process(QuestionItemFull fullItem, ZipOutputStream zout) { + public void process(QuestionItemFull fullItem, ZipOutputStream zout, Set<String> names) { String dir = fullItem.getDirectory(); VFSContainer container = qpoolFileStorage.getContainer(dir); - ZipUtil.addToZip(container, "", zout); + + String rootDir = "qitem_" + fullItem.getKey(); + List<VFSItem> items = container.getItems(); + for(VFSItem item:items) { + ZipUtil.addToZip(item, rootDir, zout); + } } + /** + * <li>List all items + * <li>Rewrite path + * <li>Assemble qti.xml + * <li>Write files at new path + * @param fullItems + * @param zout + */ public void assembleTest(List<QuestionItemFull> fullItems, ZipOutputStream zout) { - Element sectionEl = createSectionBasedAssessment("Assessment"); + ItemsAndMaterials itemAndMaterials = new ItemsAndMaterials(); for(QuestionItemFull fullItem:fullItems) { - String dir = fullItem.getDirectory(); - String rootFilename = fullItem.getRootFilename(); - VFSContainer container = qpoolFileStorage.getContainer(dir); - VFSItem rootItem = container.resolve(rootFilename); - List<String> path = new ArrayList<String>(); - collectResource(container, "", path); - - if(rootItem instanceof VFSLeaf) { - VFSLeaf rootLeaf = (VFSLeaf)rootItem; - Element el = readItemXml(rootLeaf); - Element cloneEl = (Element)el.clone(); - enrichScore(cloneEl); - enrichWithMetadata(fullItem, cloneEl); - sectionEl.add(cloneEl); - } + collectMaterials(fullItem, itemAndMaterials); } try { + byte[] buffer = new byte[FileUtils.BSIZE]; + + //write qti.xml + Element sectionEl = createSectionBasedAssessment("Assessment"); + for(Element itemEl:itemAndMaterials.getItemEls()) { + sectionEl.add(itemEl); + } zout.putNextEntry(new ZipEntry("qti.xml")); XMLWriter xw = new XMLWriter(zout, new OutputFormat(" ", true)); xw.write(sectionEl.getDocument()); zout.closeEntry(); + + //write materials + for(ItemMaterial material:itemAndMaterials.getMaterials()) { + String exportPath = material.getExportUri(); + zout.putNextEntry(new ZipEntry(exportPath)); + InputStream in = material.getLeaf().getInputStream(); + int c; + while ((c = in.read(buffer, 0, buffer.length)) != -1) { + zout.write(buffer, 0, c); + } + IOUtils.closeQuietly(in); + zout.closeEntry(); + } } catch (IOException e) { log.error("", e); } } - private void collectResource(VFSContainer container, String currentPath, List<String> path) { - List<VFSItem> items = container.getItems(); - for(VFSItem item:items) { - String itemPath = currentPath + "/" + item.getName(); - if(item instanceof VFSLeaf) { - path.add(itemPath); - } else if(item instanceof VFSContainer) { - collectResource((VFSContainer)item, itemPath, path); + public Element exportToQTIEditor(QuestionItemFull fullItem, VFSContainer editorContainer) { + ItemsAndMaterials itemAndMaterials = new ItemsAndMaterials(); + collectMaterials(fullItem, itemAndMaterials); + if(itemAndMaterials.getItemEls().isEmpty()) { + return null;//nothing found + } + + Element itemEl = itemAndMaterials.getItemEls().get(0); + //write materials + for(ItemMaterial material:itemAndMaterials.getMaterials()) { + String exportPath = material.getExportUri(); + VFSLeaf leaf = editorContainer.createChildLeaf(exportPath); + VFSManager.copyContent(material.getLeaf(), leaf); + } + return itemEl; + } + + protected void collectMaterials(QuestionItemFull fullItem, ItemsAndMaterials materials) { + String dir = fullItem.getDirectory(); + String rootFilename = fullItem.getRootFilename(); + VFSContainer container = qpoolFileStorage.getContainer(dir); + VFSItem rootItem = container.resolve(rootFilename); + + if(rootItem instanceof VFSLeaf) { + VFSLeaf rootLeaf = (VFSLeaf)rootItem; + Element el = (Element)readItemXml(rootLeaf).clone(); + Element itemEl = (Element)el.clone(); + enrichScore(itemEl); + enrichWithMetadata(fullItem, itemEl); + collectResources(itemEl, container, materials); + materials.addItemEl(itemEl); + } + } + + private void collectResources(Element el, VFSContainer container, ItemsAndMaterials materials) { + collectResourcesInMatText(el, container, materials); + collectResourcesInMatMedias(el, container, materials); + } + + /** + * Collect the file and rewrite the + * @param el + * @param container + * @param materials + * @param paths + */ + private void collectResourcesInMatText(Element el, VFSContainer container, ItemsAndMaterials materials) { + //mattext + @SuppressWarnings("unchecked") + List<Element> mattextList = el.selectNodes(".//mattext"); + for(Element mat:mattextList) { + Attribute texttypeAttr = mat.attribute("texttype"); + String texttype = texttypeAttr.getValue(); + if("text/html".equals(texttype)) { + @SuppressWarnings("unchecked") + List<Node> childElList = new ArrayList<Node>(mat.content()); + for(Node childEl:childElList) { + mat.remove(childEl); + } + + for(Node childEl:childElList) { + if(Node.CDATA_SECTION_NODE == childEl.getNodeType()) { + CDATA data = (CDATA)childEl; + boolean changed = false; + String text = data.getText(); + List<String> materialPaths = findMaterialInMatText(text); + for(String materialPath:materialPaths) { + VFSItem matVfsItem = container.resolve(materialPath); + if(matVfsItem instanceof VFSLeaf) { + String exportUri = generateExportPath(materials.getPaths(), matVfsItem); + materials.addMaterial(new ItemMaterial((VFSLeaf)matVfsItem, exportUri)); + text = text.replaceAll(materialPath, exportUri); + changed = true; + } + } + if(changed) { + mat.addCDATA(text); + } else { + mat.add(childEl); + } + } else { + mat.add(childEl); + } + } } } } + @SuppressWarnings("unchecked") + private void collectResourcesInMatMedias(Element el, VFSContainer container, ItemsAndMaterials materials) { + //matimage uri + List<Element> matList = new ArrayList<Element>(); + matList.addAll(el.selectNodes(".//matimage")); + matList.addAll(el.selectNodes(".//mataudio")); + matList.addAll(el.selectNodes(".//matvideo")); + + for(Element mat:matList) { + Attribute uriAttr = mat.attribute("uri"); + String uri = uriAttr.getValue(); + + VFSItem matVfsItem = container.resolve(uri); + if(matVfsItem instanceof VFSLeaf) { + String exportUri = generateExportPath(materials.getPaths(), matVfsItem); + ItemMaterial iMat = new ItemMaterial((VFSLeaf)matVfsItem, exportUri); + materials.addMaterial(iMat); + mat.addAttribute("uri", exportUri); + } + } + } + + private String generateExportPath(Set<String> paths, VFSItem leaf) { + String filename = leaf.getName(); + for(int count=0; paths.contains(filename) && count < 999 ; ) { + filename = VFSManager.appendNumberAtTheEndOfFilename(filename, count++); + } + paths.add(filename); + return "media/" + filename; + } + + /** + * Parse the content and collect the images source + * @param content + * @param materialPath + */ + private List<String> findMaterialInMatText(String content) { + try { + SAXParser parser = new SAXParser(); + HTMLHandler contentHandler = new HTMLHandler(); + parser.setContentHandler(contentHandler); + parser.parse(new InputSource(new StringReader(content))); + return contentHandler.getMaterialPath(); + } catch (Exception e) { + log.error("", e); + return Collections.emptyList(); + } + } + private Element createSectionBasedAssessment(String title) { DocumentFactory df = DocumentFactory.getInstance(); Document doc = df.createDocument(); @@ -210,7 +369,7 @@ public class QTIExportProcessor { private void enrichWithMetadata(QuestionItemFull fullItem, Element item) { Element qtimetadata = (Element)item.selectSingleNode("./itemmetadata/qtimetadata"); String path = fullItem.getTaxonomicPath(); - System.out.println(qtimetadata + " " + path); + System.out.println("enrichWithMetadata: " + qtimetadata + " " + path); } private void addMetadataField(String label, String entry, Element qtimetadata) { @@ -219,7 +378,6 @@ public class QTIExportProcessor { qtimetadatafield.addElement("fieldentry").setText(entry); } - /* * * <itemmetadata> @@ -304,4 +462,67 @@ public class QTIExportProcessor { <qmd_topic>Migration</qmd_topic> </itemmetadata> */ + + private static final class HTMLHandler extends DefaultHandler { + private final List<String> materialPath = new ArrayList<String>(); + + public List<String> getMaterialPath() { + return materialPath; + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) { + String elem = localName.toLowerCase(); + if("img".equals(elem)) { + String imgSrc = attributes.getValue("src"); + if(StringHelper.containsNonWhitespace(imgSrc)) { + materialPath.add(imgSrc); + } + } + } + } + + private static final class ItemsAndMaterials { + private final Set<String> paths = new HashSet<String>(); + private final List<Element> itemEls = new ArrayList<Element>(); + private final List<ItemMaterial> materials = new ArrayList<ItemMaterial>(); + + public Set<String> getPaths() { + return paths; + } + + public List<Element> getItemEls() { + return itemEls; + } + + public void addItemEl(Element el) { + itemEls.add(el); + } + + public List<ItemMaterial> getMaterials() { + return materials; + } + + public void addMaterial(ItemMaterial material) { + materials.add(material); + } + } + + private static final class ItemMaterial { + private final VFSLeaf leaf; + private final String exportUri; + + public ItemMaterial(VFSLeaf leaf, String exportUri) { + this.leaf = leaf; + this.exportUri = exportUri; + } + + public VFSLeaf getLeaf() { + return leaf; + } + + public String getExportUri() { + return exportUri; + } + } } diff --git a/src/main/java/org/olat/ims/qti/qpool/QTIImportProcessor.java b/src/main/java/org/olat/ims/qti/qpool/QTIImportProcessor.java index a1af3fae824..b3547e9a058 100644 --- a/src/main/java/org/olat/ims/qti/qpool/QTIImportProcessor.java +++ b/src/main/java/org/olat/ims/qti/qpool/QTIImportProcessor.java @@ -363,10 +363,12 @@ class QTIImportProcessor { List<Element> mattextList = el.selectNodes(".//mattext"); for(Element mat:mattextList) { Attribute texttypeAttr = mat.attribute("texttype"); - String texttype = texttypeAttr.getValue(); - if("text/html".equals(texttype)) { - String content = mat.getStringValue(); - findMaterialInMatText(content, materialPath); + if(texttypeAttr != null) { + String texttype = texttypeAttr.getValue(); + if("text/html".equals(texttype)) { + String content = mat.getStringValue(); + findMaterialInMatText(content, materialPath); + } } } //matimage uri diff --git a/src/main/java/org/olat/ims/qti/qpool/QTIQPoolServiceProvider.java b/src/main/java/org/olat/ims/qti/qpool/QTIQPoolServiceProvider.java index c65c3502cc0..767e301d0f1 100644 --- a/src/main/java/org/olat/ims/qti/qpool/QTIQPoolServiceProvider.java +++ b/src/main/java/org/olat/ims/qti/qpool/QTIQPoolServiceProvider.java @@ -24,6 +24,7 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Locale; +import java.util.Set; import java.util.zip.ZipOutputStream; import org.dom4j.Document; @@ -46,6 +47,7 @@ import org.olat.ims.qti.QTI12PreviewController; import org.olat.ims.qti.QTIConstants; import org.olat.ims.qti.editor.QTIEditHelper; import org.olat.ims.qti.editor.beecom.objects.Item; +import org.olat.ims.qti.editor.beecom.parser.ParserManager; import org.olat.ims.resources.IMSEntityResolver; import org.olat.modules.qpool.QPoolSPI; import org.olat.modules.qpool.QPoolService; @@ -151,7 +153,7 @@ public class QTIQPoolServiceProvider implements QPoolSPI { return processor.process(); } - public void importBeecomItem(Identity owner, Item item, Locale defaultLocale) { + public void importBeecomItem(Identity owner, Item item, VFSContainer sourceDir, Locale defaultLocale) { QTIImportProcessor processor = new QTIImportProcessor(owner, defaultLocale, questionItemDao, qItemTypeDao, qEduContextDao, qpoolFileStorage); @@ -166,10 +168,19 @@ public class QTIQPoolServiceProvider implements QPoolSPI { Element itemEl = (Element)doc.selectSingleNode("questestinterop/item"); QuestionItemImpl qitem = processor.processItem(itemEl, "", null, editor, editorVersion); //save to file System - VFSContainer baseDir = qpoolFileStorage.getContainer(qitem.getDirectory()); VFSLeaf leaf = baseDir.createChildLeaf(qitem.getRootFilename()); QTIEditHelper.serialiazeDoc(doc, leaf); + //process amterials + List<String> materials = processor.getMaterials(itemEl); + //copy materials + for(String material:materials) { + VFSItem sourceItem = sourceDir.resolve(material); + if(sourceItem instanceof VFSLeaf) { + VFSLeaf targetItem = baseDir.createChildLeaf(material); + VFSManager.copyContent((VFSLeaf)sourceItem, targetItem); + } + } } @Override @@ -178,9 +189,9 @@ public class QTIQPoolServiceProvider implements QPoolSPI { } @Override - public void exportItem(QuestionItemFull item, ZipOutputStream zout) { + public void exportItem(QuestionItemFull item, ZipOutputStream zout, Set<String> names) { QTIExportProcessor processor = new QTIExportProcessor(qpoolFileStorage); - processor.process(item, zout); + processor.process(item, zout, names); } public void assembleTest(List<QuestionItemShort> items, ZipOutputStream zout) { @@ -193,6 +204,13 @@ public class QTIQPoolServiceProvider implements QPoolSPI { QTIExportProcessor processor = new QTIExportProcessor(qpoolFileStorage); processor.assembleTest(fullItems, zout); } + + public Item exportToQTIEditor(QuestionItemShort qitem, VFSContainer editorContainer) { + QTIExportProcessor processor = new QTIExportProcessor(qpoolFileStorage); + QuestionItemFull fullItem = questionItemDao.loadById(qitem.getKey()); + Element itemEl = processor.exportToQTIEditor(fullItem, editorContainer); + return (Item)new ParserManager().parse(itemEl); + } @Override public void copyItem(QuestionItemFull original, QuestionItemFull copy) { diff --git a/src/main/java/org/olat/modules/qpool/QPoolSPI.java b/src/main/java/org/olat/modules/qpool/QPoolSPI.java index d2b9dc6250d..af661b466eb 100644 --- a/src/main/java/org/olat/modules/qpool/QPoolSPI.java +++ b/src/main/java/org/olat/modules/qpool/QPoolSPI.java @@ -22,6 +22,7 @@ package org.olat.modules.qpool; import java.io.File; import java.util.List; import java.util.Locale; +import java.util.Set; import java.util.zip.ZipOutputStream; import org.olat.core.gui.UserRequest; @@ -67,9 +68,10 @@ public interface QPoolSPI { /** * Export the item to the Zip * @param item - * @param out + * @param zout + * @param names Collection of the file names used in the ZIP */ - public void exportItem(QuestionItemFull item, ZipOutputStream out); + public void exportItem(QuestionItemFull item, ZipOutputStream zout, Set<String> names); /** * Copy the item attachment... diff --git a/src/main/java/org/olat/modules/qpool/QPoolService.java b/src/main/java/org/olat/modules/qpool/QPoolService.java index d44062ecddd..c7aa9a7b041 100644 --- a/src/main/java/org/olat/modules/qpool/QPoolService.java +++ b/src/main/java/org/olat/modules/qpool/QPoolService.java @@ -22,6 +22,7 @@ package org.olat.modules.qpool; import java.io.File; import java.util.List; import java.util.Locale; +import java.util.Set; import java.util.zip.ZipOutputStream; import org.olat.core.commons.persistence.ResultInfos; @@ -90,7 +91,13 @@ public interface QPoolService { //import / export public MediaResource export(List<QuestionItemShort> items, String format); - public void exportItem(QuestionItemShort item, ZipOutputStream zout); + /** + * + * @param item + * @param zout + * @param names Collection of the names used in the ZIP dd + */ + public void exportItem(QuestionItemShort item, ZipOutputStream zout, Set<String> names); public List<QuestionItem> importItems(Identity owner, Locale defaultLocale, String filename, File file); @@ -170,6 +177,8 @@ public interface QPoolService { public QItemType getItemType(String type); + public boolean delete(QItemType itemType); + //item levels administration public QEducationalContext createEducationalContext(String level); diff --git a/src/main/java/org/olat/modules/qpool/manager/AbstractExportTestResource.java b/src/main/java/org/olat/modules/qpool/manager/AbstractExportTestResource.java index b7e057e2ae3..dd433c7bf67 100644 --- a/src/main/java/org/olat/modules/qpool/manager/AbstractExportTestResource.java +++ b/src/main/java/org/olat/modules/qpool/manager/AbstractExportTestResource.java @@ -95,6 +95,8 @@ public abstract class AbstractExportTestResource implements MediaResource { exportTest(items, zout); } catch (IOException e) { log.error("", e); + } catch (Exception e) { + log.error("", e); } finally { IOUtils.closeQuietly(zout); } diff --git a/src/main/java/org/olat/modules/qpool/manager/AbstractQPoolServiceProvider.java b/src/main/java/org/olat/modules/qpool/manager/AbstractQPoolServiceProvider.java index 9633645dc32..6fef6521c81 100644 --- a/src/main/java/org/olat/modules/qpool/manager/AbstractQPoolServiceProvider.java +++ b/src/main/java/org/olat/modules/qpool/manager/AbstractQPoolServiceProvider.java @@ -29,6 +29,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Locale; +import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -142,7 +143,7 @@ public abstract class AbstractQPoolServiceProvider implements QPoolSPI { } @Override - public void exportItem(QuestionItemFull item, ZipOutputStream zout) { + public void exportItem(QuestionItemFull item, ZipOutputStream zout, Set<String> names) { String directory = item.getDirectory(); VFSContainer itemDir = getFileStorage().getContainer(directory); VFSItem file = itemDir.resolve(item.getRootFilename()); diff --git a/src/main/java/org/olat/modules/qpool/manager/ExportQItemResource.java b/src/main/java/org/olat/modules/qpool/manager/ExportQItemResource.java index 179d87c41e3..540d0b32e98 100644 --- a/src/main/java/org/olat/modules/qpool/manager/ExportQItemResource.java +++ b/src/main/java/org/olat/modules/qpool/manager/ExportQItemResource.java @@ -21,6 +21,8 @@ package org.olat.modules.qpool.manager; import java.io.IOException; import java.io.InputStream; +import java.util.HashSet; +import java.util.Set; import java.util.zip.ZipOutputStream; import javax.servlet.http.HttpServletResponse; @@ -31,8 +33,8 @@ import org.olat.core.gui.media.MediaResource; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.StringHelper; -import org.olat.modules.qpool.QuestionItemShort; import org.olat.modules.qpool.QPoolService; +import org.olat.modules.qpool.QuestionItemShort; /** * @@ -89,8 +91,9 @@ public class ExportQItemResource implements MediaResource { try { zout = new ZipOutputStream(hres.getOutputStream()); zout.setLevel(9); + Set<String> names = new HashSet<String>(); QPoolService qpoolService = CoreSpringFactory.getImpl(QPoolService.class); - qpoolService.exportItem(item, zout); + qpoolService.exportItem(item, zout, names); } catch (IOException e) { log.error("", e); } finally { diff --git a/src/main/java/org/olat/modules/qpool/manager/ExportQItemsZipResource.java b/src/main/java/org/olat/modules/qpool/manager/ExportQItemsZipResource.java new file mode 100644 index 00000000000..51f3fd1cf6a --- /dev/null +++ b/src/main/java/org/olat/modules/qpool/manager/ExportQItemsZipResource.java @@ -0,0 +1,111 @@ +/** + * <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.qpool.manager; + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.zip.ZipOutputStream; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.io.IOUtils; +import org.olat.core.CoreSpringFactory; +import org.olat.core.gui.media.MediaResource; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; +import org.olat.core.util.StringHelper; +import org.olat.modules.qpool.QPoolService; +import org.olat.modules.qpool.QuestionItemFull; + +/** + * + * Initial date: 18.04.2013<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class ExportQItemsZipResource implements MediaResource { + + private static final OLog log = Tracing.createLoggerFor(ExportQItemsZipResource.class); + + private String encoding; + private final List<QuestionItemFull> items; + + public ExportQItemsZipResource(String encoding, List<QuestionItemFull> items) { + this.encoding = encoding; + this.items = items; + } + + @Override + public String getContentType() { + return "application/octet-stream"; + } + + @Override + public Long getSize() { + return null; + } + + @Override + public InputStream getInputStream() { + return null; + } + + @Override + public Long getLastModified() { + return null; + } + + @Override + public void prepare(HttpServletResponse hres) { + try { + hres.setCharacterEncoding(encoding); + } catch (Exception e) { + log.error("", e); + } + + String label = "ExportItems"; + String file = StringHelper.transformDisplayNameToFileSystemName(label) + ".zip"; + hres.setHeader("Content-Disposition","attachment; filename=\"" + StringHelper.urlEncodeISO88591(file) + "\""); + hres.setHeader("Content-Description",StringHelper.urlEncodeISO88591(label)); + + ZipOutputStream zout = null; + try { + zout = new ZipOutputStream(hres.getOutputStream()); + zout.setLevel(9); + Set<String> names = new HashSet<String>(); + QPoolService qpoolService = CoreSpringFactory.getImpl(QPoolService.class); + for(QuestionItemFull item:items) { + qpoolService.exportItem(item, zout, names); + } + } catch (IOException e) { + log.error("", e); + } finally { + IOUtils.closeQuietly(zout); + } + } + + @Override + public void release() { + // + } +} diff --git a/src/main/java/org/olat/modules/qpool/manager/LOMConverter.java b/src/main/java/org/olat/modules/qpool/manager/MetadataConverterHelper.java similarity index 82% rename from src/main/java/org/olat/modules/qpool/manager/LOMConverter.java rename to src/main/java/org/olat/modules/qpool/manager/MetadataConverterHelper.java index 65920902678..953ddf6a515 100644 --- a/src/main/java/org/olat/modules/qpool/manager/LOMConverter.java +++ b/src/main/java/org/olat/modules/qpool/manager/MetadataConverterHelper.java @@ -19,38 +19,42 @@ */ package org.olat.modules.qpool.manager; -import java.io.InputStream; -import java.io.OutputStream; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -import org.olat.core.logging.OLog; -import org.olat.core.logging.Tracing; import org.olat.core.util.StringHelper; +import org.olat.core.util.xml.XStreamHelper; +import org.olat.modules.qpool.QuestionItem; import org.olat.modules.qpool.model.LOMDuration; +import org.olat.modules.qpool.model.QEducationalContext; +import org.olat.modules.qpool.model.QItemType; +import org.olat.modules.qpool.model.QLicense; import org.olat.modules.qpool.model.QuestionItemImpl; -import org.springframework.stereotype.Service; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.xml.sax.InputSource; +import org.olat.modules.qpool.model.TaxonomyLevelImpl; + +import com.thoughtworks.xstream.XStream; /** + * + * Some utilities to convert LOM specific date format * * Initial date: 11.03.2013<br> * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ -@Service("lomConverter") -public class LOMConverter { +public class MetadataConverterHelper { - private static final OLog log = Tracing.createLoggerFor(LOMConverter.class); + private static XStream metadatXstream = XStreamHelper.createXStreamInstance(); + static { + + metadatXstream.alias("item", QuestionItemImpl.class); + metadatXstream.alias("educationalContext", QEducationalContext.class); + metadatXstream.alias("itemType", QItemType.class); + metadatXstream.alias("license", QLicense.class); + metadatXstream.alias("taxonomyLevel", TaxonomyLevelImpl.class); + } + public static String toXml(QuestionItem item) { + return metadatXstream.toXML(item); + } + /** * P[yY][mM][dD][T[hH][nM][s[.s]S]] where:<br> * y = number of years (integer, > 0, not restricted)<br> @@ -154,7 +158,7 @@ public class LOMConverter { String intVal = durationStr.substring(0, index); return Integer.parseInt(intVal); } - + /* protected void toLom(QuestionItemImpl item, OutputStream out) { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); @@ -179,17 +183,51 @@ public class LOMConverter { protected void generalToLom(QuestionItemImpl item, Node lomEl, Document doc) { Node generalEl = lomEl.appendChild(doc.createElement("general")); - //language - Element languageEl = (Element)generalEl.appendChild(doc.createElement("language")); - languageEl.setAttribute("value", item.getLanguage()); + //identifier + + //master identifier + //title Node titleEl = generalEl.appendChild(doc.createElement("title")); stringToLom(item, item.getTitle(), titleEl, doc); //description Node descEl = generalEl.appendChild(doc.createElement("description")); stringToLom(item, item.getDescription(), descEl, doc); + //keywords + //coverage + //additional information + + //language + Element languageEl = (Element)generalEl.appendChild(doc.createElement("language")); + languageEl.setAttribute("value", item.getLanguage()); + } + + protected void taxonomyToLom(QuestionItemImpl item, Node lomEl, Document doc) { + Node generalEl = lomEl.appendChild(doc.createElement("classification")); + + } + + protected void educationalToLom(QuestionItemImpl item, Node lomEl, Document doc) { + Node generalEl = lomEl.appendChild(doc.createElement("educational")); + + } + + protected void lifecycleToLom(QuestionItemImpl item, Node lomEl, Document doc) { + Node generalEl = lomEl.appendChild(doc.createElement("lifecycle")); + + //version + //status + //urheber / contribute + + } + + protected void rightsToLom(QuestionItemImpl item, Node lomEl, Document doc) { + Node generalEl = lomEl.appendChild(doc.createElement("rights")); + + //copyright + //description } @@ -246,5 +284,5 @@ public class LOMConverter { } } return val; - } + }*/ } diff --git a/src/main/java/org/olat/modules/qpool/manager/QItemTypeDAO.java b/src/main/java/org/olat/modules/qpool/manager/QItemTypeDAO.java index 85f1c2d55cf..ad22b9d0623 100644 --- a/src/main/java/org/olat/modules/qpool/manager/QItemTypeDAO.java +++ b/src/main/java/org/olat/modules/qpool/manager/QItemTypeDAO.java @@ -94,6 +94,15 @@ public class QItemTypeDAO implements ApplicationListener<ContextRefreshedEvent> return types.get(0); } + public int countItemUsing(QItemType type) { + StringBuilder sb = new StringBuilder(); + sb.append("select count(item) from questionitem item where item.type.key=:itemTypeKey"); + return dbInstance.getCurrentEntityManager() + .createQuery(sb.toString(), Number.class) + .setParameter("itemTypeKey", type.getKey()) + .getSingleResult().intValue(); + } + public boolean delete(QItemType type) { QItemType reloadType = loadById(type.getKey()); if(reloadType.isDeletable()) { diff --git a/src/main/java/org/olat/modules/qpool/manager/QuestionPoolServiceImpl.java b/src/main/java/org/olat/modules/qpool/manager/QuestionPoolServiceImpl.java index df939359624..c14c09e2673 100644 --- a/src/main/java/org/olat/modules/qpool/manager/QuestionPoolServiceImpl.java +++ b/src/main/java/org/olat/modules/qpool/manager/QuestionPoolServiceImpl.java @@ -21,8 +21,10 @@ package org.olat.modules.qpool.manager; import java.io.File; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Locale; +import java.util.Set; import java.util.zip.ZipOutputStream; import org.olat.basesecurity.BaseSecurity; @@ -206,6 +208,9 @@ public class QuestionPoolServiceImpl implements QPoolService { public MediaResource export(List<QuestionItemShort> items, String format) { MediaResource mr = null; if(ZIP_EXPORT_FORMAT.equals(format)) { + List<Long> keys = toKeys(items); + List<QuestionItemFull> fullItems = questionItemDao.loadByIds(keys); + mr = new ExportQItemsZipResource("UTF-8", fullItems); //make a zip with all items } else { QPoolSPI selectedSp = null; @@ -221,18 +226,32 @@ public class QuestionPoolServiceImpl implements QPoolService { mr = selectedSp.exportTest(items, format); } } - + return mr; } + + private List<Long> toKeys(List<? extends QuestionItemShort> items) { + if(items == null || items.isEmpty()) return Collections.emptyList(); + List<Long> keys = new ArrayList<Long>(items.size()); + for(QuestionItemShort item:items) { + keys.add(item.getKey()); + } + return keys; + } @Override - public void exportItem(QuestionItemShort item, ZipOutputStream zout) { + public void exportItem(QuestionItemShort item, ZipOutputStream zout, Set<String> names) { QPoolSPI provider = qpoolModule.getQuestionPoolProvider(item.getFormat()); if(provider == null) { log.error("Not found provider for this format: " + item.getFormat()); } else { - QuestionItemImpl fullItem = questionItemDao.loadById(item.getKey()); - provider.exportItem(fullItem, zout); + QuestionItemFull fullItem; + if(item instanceof QuestionItemFull) { + fullItem = (QuestionItemFull)item; + } else { + fullItem = questionItemDao.loadById(item.getKey()); + } + provider.exportItem(fullItem, zout, names); } } @@ -634,6 +653,14 @@ public class QuestionPoolServiceImpl implements QPoolService { return qpoolItemTypeDao.loadByType(type); } + @Override + public boolean delete(QItemType itemType) { + if(qpoolItemTypeDao.countItemUsing(itemType) == 0) { + return qpoolItemTypeDao.delete(itemType); + } + return false; + } + @Override public QEducationalContext createEducationalContext(String level) { return qEduContextDao.create(level, true); diff --git a/src/main/java/org/olat/modules/qpool/ui/ImportController.java b/src/main/java/org/olat/modules/qpool/ui/ImportController.java index 698e2a406d7..7596affff35 100644 --- a/src/main/java/org/olat/modules/qpool/ui/ImportController.java +++ b/src/main/java/org/olat/modules/qpool/ui/ImportController.java @@ -69,6 +69,18 @@ public class ImportController extends FormBasicController { return fileEl.getUploadFile(); } + @Override + protected boolean validateFormLogic(UserRequest ureq) { + boolean allOk = true; + + fileEl.clearError(); + if(fileEl.getUploadFile() == null) { + fileEl.setErrorKey("form.mandatory.hover", null); + allOk = false; + } + return allOk & super.validateFormLogic(ureq); + } + @Override protected void formOK(UserRequest ureq) { String filename = fileEl.getUploadFileName(); diff --git a/src/main/java/org/olat/modules/qpool/ui/QuestionItemPreviewController.java b/src/main/java/org/olat/modules/qpool/ui/QuestionItemPreviewController.java index c73b67f2146..035c6c8e08c 100644 --- a/src/main/java/org/olat/modules/qpool/ui/QuestionItemPreviewController.java +++ b/src/main/java/org/olat/modules/qpool/ui/QuestionItemPreviewController.java @@ -69,25 +69,34 @@ public class QuestionItemPreviewController extends BasicController { previewPanel.setContent(null); } + public void refresh(UserRequest ureq) { + updateItem(ureq, item); + } + public void updateItem(UserRequest ureq, QuestionItem item) { this.item = item; removeAsListenerAndDispose(previewCtrl); - - Component content; - QPoolSPI spi = poolModule.getQuestionPoolProvider(item.getFormat()); - if(spi == null) { - content = getRawContent(item); + if(item == null) { + removeAsListenerAndDispose(previewCtrl); + previewCtrl = null; + previewPanel.setContent(null); } else { - previewCtrl = spi.getPreviewController(ureq, getWindowControl(), item); - if(previewCtrl == null) { + Component content; + QPoolSPI spi = poolModule.getQuestionPoolProvider(item.getFormat()); + if(spi == null) { content = getRawContent(item); } else { - listenTo(previewCtrl); - content = previewCtrl.getInitialComponent(); + previewCtrl = spi.getPreviewController(ureq, getWindowControl(), item); + if(previewCtrl == null) { + content = getRawContent(item); + } else { + listenTo(previewCtrl); + content = previewCtrl.getInitialComponent(); + } } + + previewPanel.setContent(content); } - - previewPanel.setContent(content); } private Component getRawContent(QuestionItem item) { diff --git a/src/main/java/org/olat/modules/qpool/ui/QuestionItemSummaryController.java b/src/main/java/org/olat/modules/qpool/ui/QuestionItemSummaryController.java index 3777b7bf1d7..d21d05dfa25 100644 --- a/src/main/java/org/olat/modules/qpool/ui/QuestionItemSummaryController.java +++ b/src/main/java/org/olat/modules/qpool/ui/QuestionItemSummaryController.java @@ -78,29 +78,41 @@ public class QuestionItemSummaryController extends FormBasicController { return item; } + public void refresh() { + updateItem(item, canEdit); + } + public void updateItem(QuestionItem item, boolean canEdit) { this.item = item; - - keyEl.setValue(item.getKey().toString()); - identifierEl.setValue(item.getIdentifier()); - subjectEl.setValue(item.getTitle()); - String keywords = item.getKeywords(); - keywordsEl.setValue(keywords == null ? "" : keywords); - String taxonPath = item.getTaxonomicPath(); - studyFieldEl.setValue(taxonPath == null ? "" : taxonPath); - - int usage = item.getUsage(); - String usageStr = ""; - if(usage >= 0) { - usageStr = Integer.toString(usage); - } - usageEl.setValue(usageStr); - - String description = item.getDescription(); - if(StringHelper.containsNonWhitespace(description)) { - descriptionEl.setValue(description); - } else { + if(item == null) { + identifierEl.setValue(""); + subjectEl.setValue(""); + keywordsEl.setValue("" ); + studyFieldEl.setValue(""); + usageEl.setValue(""); descriptionEl.setValue(""); + } else { + keyEl.setValue(item.getKey().toString()); + identifierEl.setValue(item.getIdentifier()); + subjectEl.setValue(item.getTitle()); + String keywords = item.getKeywords(); + keywordsEl.setValue(keywords == null ? "" : keywords); + String taxonPath = item.getTaxonomicPath(); + studyFieldEl.setValue(taxonPath == null ? "" : taxonPath); + + int usage = item.getUsage(); + String usageStr = ""; + if(usage >= 0) { + usageStr = Integer.toString(usage); + } + usageEl.setValue(usageStr); + + String description = item.getDescription(); + if(StringHelper.containsNonWhitespace(description)) { + descriptionEl.setValue(description); + } else { + descriptionEl.setValue(""); + } } } diff --git a/src/main/java/org/olat/modules/qpool/ui/QuestionPoolMainEditorController.java b/src/main/java/org/olat/modules/qpool/ui/QuestionPoolMainEditorController.java index 185df7a4b6d..5af9bd69fb3 100644 --- a/src/main/java/org/olat/modules/qpool/ui/QuestionPoolMainEditorController.java +++ b/src/main/java/org/olat/modules/qpool/ui/QuestionPoolMainEditorController.java @@ -140,7 +140,7 @@ public class QuestionPoolMainEditorController extends BasicController implements String dropId = e.getDroppedNodeId(); //drop id w_o_fi1000002357-4 doDrop(targetId, dropId); - } else { + } else if(menuTree.getSelectedNode() != null){ TreeNode node = menuTree.getSelectedNode(); Object uNode = node.getUserObject(); if("menu.admin".equals(uNode)) { @@ -288,7 +288,7 @@ public class QuestionPoolMainEditorController extends BasicController implements myQuestionsCtrl.setStackedController(stackPanel); listenTo(myQuestionsCtrl); } else { - myQuestionsCtrl.updateSource(source); + myQuestionsCtrl.updateSource(ureq, source); } currentCtrl = myQuestionsCtrl; content.setContent(myQuestionsCtrl.getInitialComponent()); @@ -302,7 +302,7 @@ public class QuestionPoolMainEditorController extends BasicController implements markedQuestionsCtrl.setStackedController(stackPanel); listenTo(markedQuestionsCtrl); } else { - markedQuestionsCtrl.updateSource(source); + markedQuestionsCtrl.updateSource(ureq, source); } currentCtrl = markedQuestionsCtrl; content.setContent(markedQuestionsCtrl.getInitialComponent()); @@ -316,7 +316,7 @@ public class QuestionPoolMainEditorController extends BasicController implements selectedPoolCtrl.setStackedController(stackPanel); listenTo(selectedPoolCtrl); } else { - selectedPoolCtrl.updateSource(source); + selectedPoolCtrl.updateSource(ureq, source); } currentCtrl = selectedPoolCtrl; content.setContent(selectedPoolCtrl.getInitialComponent()); @@ -328,7 +328,7 @@ public class QuestionPoolMainEditorController extends BasicController implements sharedItemsCtrl.setStackedController(stackPanel); listenTo(sharedItemsCtrl); } else { - sharedItemsCtrl.updateSource(new SharedItemsSource(group, getIdentity(), ureq.getUserSession().getRoles())); + sharedItemsCtrl.updateSource(ureq, new SharedItemsSource(group, getIdentity(), ureq.getUserSession().getRoles())); } currentCtrl = sharedItemsCtrl; content.setContent(sharedItemsCtrl.getInitialComponent()); @@ -341,7 +341,7 @@ public class QuestionPoolMainEditorController extends BasicController implements collItemsCtrl.setStackedController(stackPanel); listenTo(collItemsCtrl); } else { - collItemsCtrl.updateSource(source); + collItemsCtrl.updateSource(ureq, source); } currentCtrl = collItemsCtrl; content.setContent(collItemsCtrl.getInitialComponent()); diff --git a/src/main/java/org/olat/modules/qpool/ui/QuestionsController.java b/src/main/java/org/olat/modules/qpool/ui/QuestionsController.java index f70848c18f1..5863a2c44a2 100644 --- a/src/main/java/org/olat/modules/qpool/ui/QuestionsController.java +++ b/src/main/java/org/olat/modules/qpool/ui/QuestionsController.java @@ -102,8 +102,10 @@ public class QuestionsController extends BasicController implements StackedContr // } - public void updateSource(QuestionItemsSource source) { + public void updateSource(UserRequest ureq, QuestionItemsSource source) { listCtrl.updateSource(source); + detailsCtrl.refresh(); + previewCtrl.refresh(ureq); } public QuestionItemShort getQuestionAt(int index) { diff --git a/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_de.properties index 382ebc03e66..e9e7f85800f 100644 --- a/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_de.properties @@ -51,9 +51,7 @@ classification.taxonomy.level=Fachbereich classification.taxonomy.parents=Path educational=Educational educational.context=Level -educational.context.deleted=Level wurde erfolgreich gelöscht -educational.context.notdeleted=Level wurde nicht gelöscht, probably in use -educational.learningTime=Durschnittliche Bearbeitungszeit +educational.learningTime=Durchschnittliche Bearbeitungszeit educational.learningTime.day=d educational.learningTime.hour=h educational.learningTime.minute=m @@ -85,7 +83,7 @@ technical.editor=Editor technical.editorVersion=Editor Version technical.format=Format technical.creation=Erstellt -technical.lastModified=Letzte Anderung +technical.lastModified=Letzte \u00C4nderung rights=Rechte rights.copyright=Copyright rights.description=Lizenz @@ -97,7 +95,7 @@ sharing=Freigabe / Autoren sharing.authors=Autoren sharing.author.name=Name sharing.shares=Gruppen -manage.owners=Authoren +manage.owners=Autoren item.level=Level item.shared=Frage {0} wurde freigegeben. item.pooled=Frage {0} wurde im Pool hinzugefügt. @@ -125,8 +123,9 @@ item.type.fib=Fill-in-Black item.type.sc=Single-Choice item.type.kprim=KPrim item.type.essay=Essay -author.item=Authoren -author.choose.title=Authoren auswählen +item.type.unkown=Unbekannt +author.item=Autoren +author.choose.title=Autoren auswählen author.confirm.title=Bestätigen share.item=Freigeben unshare.item=Entfernen @@ -138,5 +137,5 @@ select.item=Bearbeiten export.item=Export import.item=Import error.input.toolong=Leider ist Ihr gerade eingegebener Text mit {1} Zeichen zu lang. Bitte beschr\u00E4nken Sie sich auf maximal {0} Zeichen. -share.options=Wollen Sie andere Personen diese Frage erlauben zu editieren? +share.options=Wollen Sie anderen Personen diese Frage erlauben zu editieren? share.editable=Editieren \ No newline at end of file diff --git a/src/main/java/org/olat/modules/qpool/ui/admin/QItemTypesAdminController.java b/src/main/java/org/olat/modules/qpool/ui/admin/QItemTypesAdminController.java index 3380a13dddd..fb673ae3cf3 100644 --- a/src/main/java/org/olat/modules/qpool/ui/admin/QItemTypesAdminController.java +++ b/src/main/java/org/olat/modules/qpool/ui/admin/QItemTypesAdminController.java @@ -205,8 +205,12 @@ public class QItemTypesAdminController extends FormBasicController { } private void doDelete(UserRequest ureq, QItemType type) { - //qpoolService.deletePool(pool); - reloadModel(); + if(qpoolService.delete(type)) { + reloadModel(); + showInfo("item.type.deleted"); + } else { + showError("item.type.notdeleted"); + } } private void doEdit(UserRequest ureq, QItemType type) { diff --git a/src/main/java/org/olat/modules/qpool/ui/admin/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/qpool/ui/admin/_i18n/LocalStrings_de.properties index 28f00b32e26..42648dabfa9 100644 --- a/src/main/java/org/olat/modules/qpool/ui/admin/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/modules/qpool/ui/admin/_i18n/LocalStrings_de.properties @@ -16,4 +16,8 @@ delete.license.confirm=Wollen Sie wirklich dieser Lizenz l create.level=Level erstellen create.license=Lizenz erstellen create.type=Typ erstellen -add.taxonomyLevel=Level erstellen \ No newline at end of file +add.taxonomyLevel=Level erstellen +educational.context.deleted=Level wurde erfolgreich gelöscht +educational.context.notdeleted=Level wurde nicht gelöscht, probably in use +item.type.deleted=Typ wurde erfolgreich gelöscht +item.type.notdeleted=Typ wurde nicht gelöscht, probably in use \ No newline at end of file diff --git a/src/main/java/org/olat/modules/qpool/ui/edit/EducationalMetadataController.java b/src/main/java/org/olat/modules/qpool/ui/edit/EducationalMetadataController.java index aab7b492d0c..872d9cde85f 100644 --- a/src/main/java/org/olat/modules/qpool/ui/edit/EducationalMetadataController.java +++ b/src/main/java/org/olat/modules/qpool/ui/edit/EducationalMetadataController.java @@ -77,7 +77,11 @@ public class EducationalMetadataController extends FormBasicController { if(context == null || context.getLevel() == null) { contextEl.setValue(""); } else { - contextEl.setValue(context.getLevel()); + String translation = translate("item.level." + context.getLevel().toLowerCase()); + if(translation.length() > 128) { + translation = context.getLevel(); + } + contextEl.setValue(translation); } String learningTime = item.getEducationalLearningTime() == null ? "" : item.getEducationalLearningTime(); diff --git a/src/main/java/org/olat/modules/qpool/ui/edit/EducationalMetadataEditController.java b/src/main/java/org/olat/modules/qpool/ui/edit/EducationalMetadataEditController.java index dd94dfbca55..b2d825f3fb6 100644 --- a/src/main/java/org/olat/modules/qpool/ui/edit/EducationalMetadataEditController.java +++ b/src/main/java/org/olat/modules/qpool/ui/edit/EducationalMetadataEditController.java @@ -34,7 +34,7 @@ import org.olat.core.gui.control.WindowControl; import org.olat.core.util.Util; import org.olat.modules.qpool.QPoolService; import org.olat.modules.qpool.QuestionItem; -import org.olat.modules.qpool.manager.LOMConverter; +import org.olat.modules.qpool.manager.MetadataConverterHelper; import org.olat.modules.qpool.model.LOMDuration; import org.olat.modules.qpool.model.QEducationalContext; import org.olat.modules.qpool.model.QuestionItemImpl; @@ -74,7 +74,11 @@ public class EducationalMetadataEditController extends FormBasicController { int count = 0; for(QEducationalContext level:levels) { contextKeys[count] = level.getLevel(); - contextValues[count++] = "item.level." + level.getLevel().toLowerCase(); + String translation = translate("item.level." + level.getLevel().toLowerCase()); + if(translation.length() > 128) { + translation = level.getLevel(); + } + contextValues[count++] = translation; } contextEl = uifactory.addDropdownSingleselect("educational.context", "educational.context", formLayout, contextKeys, contextValues, null); @@ -86,7 +90,7 @@ public class EducationalMetadataEditController extends FormBasicController { learningTimeContainer.setLabel("educational.learningTime", null); formLayout.add(learningTimeContainer); - LOMDuration duration = LOMConverter.convertDuration(item.getEducationalLearningTime()); + LOMDuration duration = MetadataConverterHelper.convertDuration(item.getEducationalLearningTime()); learningTimeDayElement = uifactory.addIntegerElement("learningTime.day", "", duration.getDay(), learningTimeContainer); learningTimeDayElement.setDisplaySize(3); learningTimeDayElement.setMandatory(true); @@ -135,7 +139,7 @@ public class EducationalMetadataEditController extends FormBasicController { int hour = learningTimeHourElement.getIntValue(); int minute = learningTimeMinuteElement.getIntValue(); int seconds = learningTimeSecondElement.getIntValue(); - String timeStr = LOMConverter.convertDuration(day, hour, minute, seconds); + String timeStr = MetadataConverterHelper.convertDuration(day, hour, minute, seconds); itemImpl.setEducationalLearningTime(timeStr); } item = qpoolService.updateItem(item); diff --git a/src/main/java/org/olat/modules/qpool/ui/edit/LifecycleMetadataEditController.java b/src/main/java/org/olat/modules/qpool/ui/edit/LifecycleMetadataEditController.java index 9d6ab1d3349..8a7b64c33b6 100644 --- a/src/main/java/org/olat/modules/qpool/ui/edit/LifecycleMetadataEditController.java +++ b/src/main/java/org/olat/modules/qpool/ui/edit/LifecycleMetadataEditController.java @@ -64,7 +64,7 @@ public class LifecycleMetadataEditController extends FormBasicController { protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { setFormTitle("lifecycle"); - versionEl = uifactory.addTextElement("lifecycle.version", "lifecycle.version", 50, "", formLayout); + versionEl = uifactory.addTextElement("lifecycle.version", "lifecycle.version", 50, item.getItemVersion(), formLayout); String[] statusTypeKeys = QuestionStatus.valueString(); String[] statusTypeValues = new String[statusTypeKeys.length]; @@ -73,6 +73,9 @@ public class LifecycleMetadataEditController extends FormBasicController { } statusEl = uifactory.addDropdownSingleselect("lifecycle.status", "lifecycle.status", formLayout, statusTypeKeys, statusTypeValues, null); + if(item.getQuestionStatus() != null) { + statusEl.select(item.getQuestionStatus().name(), true); + } FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); buttonsCont.setRootForm(mainForm); diff --git a/src/main/java/org/olat/modules/qpool/ui/edit/QuestionMetadataController.java b/src/main/java/org/olat/modules/qpool/ui/edit/QuestionMetadataController.java index 48e68761693..71125b90335 100644 --- a/src/main/java/org/olat/modules/qpool/ui/edit/QuestionMetadataController.java +++ b/src/main/java/org/olat/modules/qpool/ui/edit/QuestionMetadataController.java @@ -85,7 +85,11 @@ public class QuestionMetadataController extends FormBasicController { if(type == null || type.getType() == null) { typeEl.setValue(""); } else { - typeEl.setValue(type.getType()); + String translation = translate("item.type." + type.getType().toLowerCase()); + if(translation.length() > 128) { + translation = type.getType(); + } + typeEl.setValue(translation); } difficultyEl.setValue(toString(item.getDifficulty())); diff --git a/src/main/java/org/olat/modules/qpool/ui/edit/QuestionMetadataEditController.java b/src/main/java/org/olat/modules/qpool/ui/edit/QuestionMetadataEditController.java index 8964b9c1f59..92d1e13446d 100644 --- a/src/main/java/org/olat/modules/qpool/ui/edit/QuestionMetadataEditController.java +++ b/src/main/java/org/olat/modules/qpool/ui/edit/QuestionMetadataEditController.java @@ -73,21 +73,33 @@ public class QuestionMetadataEditController extends FormBasicController { int count = 0; for(QItemType type:types) { typeKeys[count] = type.getType(); - typeValues[count++] = translate("item.type." + type.getType().toLowerCase()); + String translation = translate("item.type." + type.getType().toLowerCase()); + if(translation.length() > 128) { + typeValues[count++] = typeKeys[count]; + } else { + typeValues[count++] = translation; + } } typeEl = uifactory.addDropdownSingleselect("question.type", "question.type", formLayout, typeKeys, typeValues, null); + if(item.getType() != null) { + typeEl.select(item.getType().getType(), true); + } - difficultyEl = uifactory.addTextElement("question.difficulty", "question.difficulty", 10, "", formLayout); + String difficulty = toString(item.getDifficulty()); + difficultyEl = uifactory.addTextElement("question.difficulty", "question.difficulty", 10, difficulty, formLayout); difficultyEl.setExampleKey("question.difficulty.example", null); difficultyEl.setDisplaySize(4); - stdevDifficultyEl = uifactory.addTextElement("question.stdevDifficulty", "question.stdevDifficulty", 10, "", formLayout); + + String stdevDifficulty = toString(item.getStdevDifficulty()); + stdevDifficultyEl = uifactory.addTextElement("question.stdevDifficulty", "question.stdevDifficulty", 10, stdevDifficulty, formLayout); stdevDifficultyEl.setExampleKey("question.stdevDifficulty.example", null); stdevDifficultyEl.setDisplaySize(4); - differentiationEl = uifactory.addTextElement("question.differentiation", "question.differentiation", 10, "", formLayout); + String differentiation = toString(item.getDifferentiation()); + differentiationEl = uifactory.addTextElement("question.differentiation", "question.differentiation", 10, differentiation, formLayout); differentiationEl.setExampleKey("question.differentiation.example", null); differentiationEl.setDisplaySize(4); - - numAnswerAltEl = uifactory.addTextElement("question.numOfAnswerAlternatives", "question.numOfAnswerAlternatives", 10, "", formLayout); + String numAnswerAlt = item.getNumOfAnswerAlternatives() < 0 ? "" : Integer.toString(item.getNumOfAnswerAlternatives()); + numAnswerAltEl = uifactory.addTextElement("question.numOfAnswerAlternatives", "question.numOfAnswerAlternatives", 10, numAnswerAlt, formLayout); numAnswerAltEl.setDisplaySize(4); uifactory.addStaticTextElement("question.usage", Integer.toString(item.getUsage()), formLayout); @@ -98,6 +110,9 @@ public class QuestionMetadataEditController extends FormBasicController { }; assessmentTypeEl = uifactory.addDropdownSingleselect("question.assessmentType", "question.assessmentType", formLayout, assessmentTypeKeys, assessmentTypeValues, null); + if(StringHelper.containsNonWhitespace(item.getAssessmentType())) { + assessmentTypeEl.select(item.getAssessmentType(), true); + } FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); buttonsCont.setRootForm(mainForm); @@ -200,6 +215,13 @@ public class QuestionMetadataEditController extends FormBasicController { return null; } + private String toString(BigDecimal val) { + if(val == null) { + return ""; + } + return val.toPlainString(); + } + private int toInt(String val) { if(StringHelper.containsNonWhitespace(val)) { return Integer.parseInt(val); diff --git a/src/main/java/org/olat/modules/qpool/ui/edit/TechnicalMetadataEditController.java b/src/main/java/org/olat/modules/qpool/ui/edit/TechnicalMetadataEditController.java index c6256b79f69..794f9857bc4 100644 --- a/src/main/java/org/olat/modules/qpool/ui/edit/TechnicalMetadataEditController.java +++ b/src/main/java/org/olat/modules/qpool/ui/edit/TechnicalMetadataEditController.java @@ -64,9 +64,9 @@ public class TechnicalMetadataEditController extends FormBasicController { @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { setFormTitle("technical"); - - editorEl = uifactory.addTextElement("technical.editor", "technical.editor", 50, "", formLayout); - editorVersionEl = uifactory.addTextElement("technical.editorVersion", "technical.editorVersion", 50, "", formLayout); + + editorEl = uifactory.addTextElement("technical.editor", "technical.editor", 50, item.getEditor(), formLayout); + editorVersionEl = uifactory.addTextElement("technical.editorVersion", "technical.editorVersion", 50, item.getEditorVersion(), formLayout); String[] formatKeys = new String[]{ QTIConstants.QTI_12_FORMAT }; formatEl = uifactory.addDropdownSingleselect("technical.format", "technical.format", formLayout, diff --git a/src/main/java/org/olat/modules/qpool/ui/wizard/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/qpool/ui/wizard/_i18n/LocalStrings_de.properties index 858ba080511..4002bd2812b 100644 --- a/src/main/java/org/olat/modules/qpool/ui/wizard/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/modules/qpool/ui/wizard/_i18n/LocalStrings_de.properties @@ -1,6 +1,6 @@ #Mon Mar 02 09:54:04 CET 2009 -author.item=Authoren -author.choose.title=Authoren auswählen +author.item=Autoren +author.choose.title=Autoren auswählen author.confirm.title=Bestätigen table.user.login=$org.olat.admin.user\:table.user.login export.type=Typ diff --git a/src/main/webapp/static/js/functions.js b/src/main/webapp/static/js/functions.js index c1d7d802bbd..741d17b60e3 100644 --- a/src/main/webapp/static/js/functions.js +++ b/src/main/webapp/static/js/functions.js @@ -352,6 +352,19 @@ Array.prototype.search = function(s,q){ return false; } +if(!Function.prototype.curry) { + Function.prototype.curry = function() { + if (arguments.length<1) { + return this; //nothing to curry with - return function + } + var __method = this; + var args = Array.prototype.slice.call(arguments); + return function() { + return __method.apply(this, args.concat(Array.prototype.slice.call(arguments))); + } + } +} + if(!Array.prototype.indexOf) { Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) { "use strict"; @@ -1064,7 +1077,8 @@ function showMessageBox(type, title, message, buttonCallback){ //possible if the user has closed the window } } - }).dialog('open'); + }).dialog('open').dialog("widget").css('z-index', 11000); + } } diff --git a/src/main/webapp/static/js/js.plugins.min.js b/src/main/webapp/static/js/js.plugins.min.js index 1edaad76963..31b56ddb462 100644 --- a/src/main/webapp/static/js/js.plugins.min.js +++ b/src/main/webapp/static/js/js.plugins.min.js @@ -1,4 +1,4 @@ -OPOL={};var o2c=0;var o3c=new Array();o_info.guibusy=false;o_info.linkbusy=false;o_info.debug=true;var BLoader={_ajaxLoadedJS:new Array(),_isAlreadyLoadedJS:function(b){var a=true;jQuery("head script[src]").each(function(d,c){if(jQuery(c).attr("src").indexOf(b)!=-1){a=false}});if(jQuery.inArray(b,this._ajaxLoadedJS)!=-1){a=false}return !a},loadJS:function(b,c,a){if(!this._isAlreadyLoadedJS(b)){if(o_info.debug){o_log("BLoader::loadJS: loading ajax::"+a+" url::"+b)}if(a){jQuery.ajax(b,{async:false,dataType:"script",success:function(d,f,e){}});this._ajaxLoadedJS.push(b)}else{jQuery.getScript(b)}if(o_info.debug){o_log("BLoader::loadJS: loading DONE url::"+b)}}else{if(o_info.debug){o_log("BLoader::loadJS: already loaded url::"+b)}}},executeGlobalJS:function(jsString,contextDesc){try{if(window.execScript){window.execScript(jsString)}else{window.eval(jsString)}}catch(e){if(console){console.log(contextDesc,"cannot execute js",jsString)}if(o_info.debug){o_logerr("BLoader::executeGlobalJS: Error when executing JS code in contextDesc::"+contextDesc+' error::"'+showerror(e)+" for: "+escape(jsString))}if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","BLoader::executeGlobalJS: Error when executing JS code in contextDesc::"+contextDesc+' error::"'+showerror(e)+" for: "+escape(jsString),"functions.js::BLoader::executeGlobalJS::"+contextDesc)}if(window.location.href.indexOf("o_winrndo")!=-1){window.location.reload()}else{window.location.href=window.location.href+(window.location.href.indexOf("?")!=-1?"&":"?")+"o_winrndo=1"}}},loadCSS:function(b,o,q){var r=window.document;try{if(r.createStyleSheet){var j=r.styleSheets;var d=0;var p=0;for(i=0;i<j.length;i++){var m=j[i];var g=m.href;if(g==b){d++;if(m.disabled){m.disabled=false;return}else{if(o_info.debug){o_logwarn("BLoader::loadCSS: style: "+b+" already in document and not disabled! (duplicate add)")}return}}if(m.id=="b_theme_css"){p=i}}if(d>1&&o_info.debug){o_logwarn("BLoader::loadCSS: apply styles: num of stylesheets found was not 0 or 1:"+d)}if(q){p=j.length}var f=r.createStyleSheet(b,p)}else{var c=jQuery("#"+o);if(c&&c.size()>0){if(o_info.debug){o_logwarn("BLoader::loadCSS: stylesheet already found in doc when trying to add:"+b+", with id "+o)}return}else{var a=jQuery('<link id="'+o+'" rel="stylesheet" type="text/css" href="'+b+'">');if(q){a.insertBefore(jQuery("#b_fontSize_css"))}else{a.insertBefore(jQuery("#b_theme_css"))}}}}catch(n){if(console){console.log(n)}if(o_info.debug){o_logerr("BLoader::loadCSS: Error when loading CSS from URL::"+b)}if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","BLoader::loadCSS: Error when loading CSS from URL::"+b,"functions.js::BLoader::loadCSS")}}},unLoadCSS:function(a,m){var n=window.document;try{if(n.createStyleSheet){var f=n.styleSheets;var d=0;var o=a;var b=window.location.href.substring(0,window.location.href.indexOf("/",8));if(a.indexOf(b)==0){o=a.substring(b.length)}for(i=0;i<f.length;i++){var g=f[i].href;if(g==a||g==o){d++;if(!f[i].disabled){f[i].disabled=true}else{if(o_info.debug){o_logwarn("stylesheet: when removing: matching url, but already disabled! url:"+g)}}}}if(d!=1&&o_info.debug){o_logwarn("stylesheet: when removeing: num of stylesheets found was not 1:"+d)}}else{var c=jQuery("#"+m);if(c){c.href="";c.remove();c=null;return}else{if(o_info.debug){o_logwarn("no link with id found to remove, id:"+m+", url "+a)}}}}catch(j){if(o_info.debug){o_logerr("BLoader::unLoadCSS: Error when unloading CSS from URL::"+a)}if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","BLoader::unLoadCSS: Error when unloading CSS from URL::"+a,"functions.js::BLoader::loadCSS")}}}};var BFormatter={formatLatexFormulas:function(b){try{if(jsMath){if(jsMath.loaded){jsMath.ProcessBeforeShowing.curry(b).delay(0.01)}else{jsMath.Autoload.LoadJsMath();BFormatter.formatLatexFormulas.delay(0.1)}}else{if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","BFormatter::formatLatexFormulas: can not format latex formulas, jsMath not installed. Check your logfile","functions.js::BFormatter::formatLatexFormulas")}}}catch(a){if(o_info.debug){o_log("error in BFormatter.formatLatexFormulas: "+showerror(a))}}}};function o_init(){try{o_getMainWin().o_afterserver()}catch(a){if(o_info.debug){o_log("error in o_init: "+showerror(a))}}}function b_initEmPxFactor(){o_info.emPxFactor=jQuery("#b_width_1em").width();if(o_info.emPxFactor==0||o_info.emPxFactor=="undefined"){o_info.emPxFactor=12;if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","Could not read with of element b_width_1em, set o_info.emPxFactor to 12","functions.js")}}}function o_getMainWin(){try{if(window.opener&&window.opener.OPOL){return window.opener}else{if(window.OPOL){return window}}}catch(a){if(o_info.debug){o_logerr('Exception while getting main window. rror::"'+showerror(a))}if(B_AjaxLogger.isDebugEnabled()){B_AjaxLogger.logDebug('Exception while getting main window. rror::"'+showerror(a),"functions.js")}}throw"Can not find main OpenOLAT window"}function o_beforeserver(){o_info.linkbusy=true;showAjaxBusy();if(window.suppressOlatOnUnloadOnce){window.suppressOlatOnUnloadOnce=false}else{if(window.olatonunload){olatonunload()}}}function o_afterserver(){o2c=0;o_info.linkbusy=false;removeAjaxBusy()}function o2cl(){if(o_info.linkbusy){return false}else{var a=(o2c==0||confirm(o_info.dirty_form));if(a){o_beforeserver()}return a}}function o3cl(d){if(o_info.linkbusy){return false}else{var b=o3c1.indexOf(d)>-1;var a=(b&&o3c1.length>1)||o3c1.length>0;var c=(!a||confirm(o_info.dirty_form));if(c){o_beforeserver()}return c}}function o_onc(a){var b=a.responseText;BLoader.executeGlobalJS("o_info.last_o_onc="+b+";","o_onc");o_ainvoke(o_info.last_o_onc,false)}function o_allowNextClick(){o_info.linkbusy=false;removeAjaxBusy()}function removeBusyAfterDownload(c,b,a){o2c=0;o_afterserver()}Array.prototype.search=function(c,d){var a=this.length;for(var b=0;b<a;b++){if(this[b].constructor==Array){if(this[b].search(c,d)){return true;break}}else{if(d){if(this[b].indexOf(c)!=-1){return true;break}}else{if(this[b]==c){return true;break}}}}return false};if(!Array.prototype.indexOf){Array.prototype.indexOf=function(c){if(this==null){throw new TypeError()}var d=Object(this);var a=d.length>>>0;if(a===0){return -1}var e=0;if(arguments.length>1){e=Number(arguments[1]);if(e!=e){e=0}else{if(e!=0&&e!=Infinity&&e!=-Infinity){e=(e>0||-1)*Math.floor(Math.abs(e))}}}if(e>=a){return -1}var b=e>=0?e:Math.max(a-Math.abs(e),0);for(;b<a;b++){if(b in d&&d[b]===c){return b}}return -1}}var b_onDomReplacementFinished_callbacks=new Array();function b_AddOnDomReplacementFinishedCallback(a){var b=jQuery(document).ooLog().isDebugEnabled();if(b){jQuery(document).ooLog("debug","callback stack size: "+b_onDomReplacementFinished_callbacks.length,"functions.js ADD")}if(b&&jQuery.browser.mozilla&&!jQuery.browser.webkit){jQuery(document).ooLog("debug","stack content"+b_onDomReplacementFinished_callbacks.toSource(),"functions.js ADD")}b_onDomReplacementFinished_callbacks.push(a);if(b){jQuery(document).ooLog("debug","push to callback stack, func: "+a,"functions.js ADD")}}var b_changedDomEl=new Array();function b_AddOnDomReplacementFinishedUniqueCallback(a){if(a.constructor==Array){if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","add: its an ARRAY! ","functions.js ADD")}if(b_onDomReplacementFinished_callbacks.search(a[0])){if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","push to callback stack, already there!!: "+a[0],"functions.js ADD")}return}}b_AddOnDomReplacementFinishedCallback(a)}var o_debug_trid=0;function o_ainvoke(H){if(H==undefined){return}o_info.inainvoke=true;var D=H.cmdcnt;if(D>0){b_changedDomEl=new Array();if(o_info.debug){o_debug_trid++}var v=H.cmds;for(var N=0;N<D;N++){var E=v[N];var x=E.cmd;var L=E.cda;var O=E.w;var b=this.window;var F;if(b){switch(x){case 1:var G=L.e;BLoader.executeGlobalJS(G,"o_ainvoker::jsexec");if(o_info.debug){o_log("c1: execute jscode: "+G)}case 2:var s=L.cc;var B=L.cps;for(var K=0;K<s;K++){var h=B[K];var g=h.cid;var J=h.cidvis;var u=h.hfrag;var I=h.jsol;var f=h.hdr;if(o_info.debug){o_log("c2: redraw: "+h.cname+" ("+g+") "+h.hfragsize+" bytes, listener(s): "+h.clisteners)}var Q=f+"\n\n"+u;var z="";var M=false;var y=jQuery("#o_c"+g);if(y==null||(y.length==0)){y=jQuery("#o_fi"+g);M=true}if(y!=null){if(J){y.css("display","")}else{y.css("display","none")}if(M){y.replaceWith(Q)}else{y.empty();try{y.html(Q)}catch(T){if(console){console.log(T)}if(console){console.log("Fragment",Q)}}b_changedDomEl.push("o_c"+g)}y=null;if(z!=""){z.each(function(e){BLoader.executeGlobalJS(e,"o_ainvoker::inscripts")})}if(I!=""){BLoader.executeGlobalJS(I,"o_ainvoker::jsol")}}}break;case 3:b.o2c=0;var R=L.rurl;b.o_afterserver();b.document.location.replace(R);break;case 5:b.o2c=0;var R=L.rurl;b.o_afterserver();b.document.location.replace(R);break;case 6:b.o2c=0;b.o_afterserver();break;case 7:var n=b.document.location;var w=n.protocol+"//"+n.hostname;if(n.port!=""){w+=":"+n.port}var t=L.cssrm;for(K=0;K<t.length;K++){var A=t[K];var C=A.id;var d=w+A.url;BLoader.unLoadCSS(d,C);if(o_info.debug){o_log("c7: rm css: id:"+C+" ,url:'"+d+"'")}}var P=L.cssadd;for(k=0;k<P.length;k++){var A=P[k];var C=A.id;var d=w+A.url;var m=A.pt;BLoader.loadCSS(d,C,m);if(o_info.debug){o_log("c7: add css: id:"+C+" ,url:'"+d+"'")}}var o=L.jsadd;for(l=0;l<o.length;l++){var A=o[l];var S=A.before;if(jQuery.type(S)==="string"){BLoader.executeGlobalJS(S,"o_ainvoker::preJsAdd")}var d=A.url;var p=A.enc;if(jQuery.type(d)==="string"){BLoader.loadJS(d,p,true)}if(o_info.debug){o_log("c7: add js: "+d)}}break;default:if(o_info.debug){o_log("?: unknown command "+x)}if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","Error in o_ainvoke(), ?: unknown command "+x,"functions.js")}break}}else{if(o_info.debug){o_log("could not find window??")}if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","Error in o_ainvoke(), could not find window??","functions.js")}}}var a=b_onDomReplacementFinished_callbacks.length;if(jQuery.browser.mozilla&&!jQuery.browser.webkit){if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","stack content"+b_onDomReplacementFinished_callbacks.toSource(),"functions.js")}}for(mycounter=0;a>mycounter;mycounter++){if(mycounter>50){if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","Stopped executing DOM replacement callback functions - to many functions::"+b_onDomReplacementFinished_callbacks.length,"functions.js")}break}if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","Stacksize before shift: "+b_onDomReplacementFinished_callbacks.length,"functions.js")}var q=b_onDomReplacementFinished_callbacks.shift();if(typeof q.length==="number"){if(q[0]=="glosshighlighter"){var c=q[1];if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","arr fct: "+c,"functions.js")}q=c}}if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","Executing DOM replacement callback function #"+mycounter+" with timeout funct::"+q,"functions.js")}q();if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","Stacksize after timeout: "+b_onDomReplacementFinished_callbacks.length,"functions.js")}}}o_info.inainvoke=false}function clearAfterAjaxIframeCall(){if(o_info.linkbusy){o_afterserver();showMessageBox("info",o_info.i18n_noresponse_title,o_info.i18n_noresponse,undefined)}}function showAjaxBusy(){if(o_info.linkbusy){try{jQuery("#b_ajax_busy").delay(500).queue(function(b){jQuery(this).addClass("b_ajax_busy");jQuery("#b_body").addClass("b_ajax_busy")})}catch(a){}}return}function removeAjaxBusy(){try{jQuery("#b_ajax_busy").delay(500).queue(function(b){jQuery(this).removeClass("b_ajax_busy");jQuery("#b_body").removeClass("b_ajax_busy")})}catch(a){}}var htmlEditorEnabled=(jQuery.browser.msie||jQuery.browser.mozilla);var scormPlayerEnabled=(jQuery.browser.msie||jQuery.browser.mozilla||jQuery.browser.webkit);function setFormDirty(c){o2c=1;var a=document.getElementById(c);if(a!=null){var b=a.olat_fosm_0;if(b==null){b=a.olat_fosm}if(b){b.className="b_button b_button_dirty"}}else{if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","Error in setFormDirty, myForm was null for formId="+c,"functions.js")}}}function contextHelpWindow(a){helpWindow=window.open(a,"HelpWindow","height=760, width=940, left=0, top=0, location=no, menubar=no, resizable=yes, scrollbars=yes, toolbar=no");helpWindow.focus()}function o_openPopUp(b,d,c,a,e){attributes="height="+a+", width="+c+", resizable=yes, scrollbars=yes, left=100, top=100, ";if(e){attributes+="location=yes, menubar=yes, status=yes, toolbar=yes"}else{attributes+="location=no, menubar=no, status=no, toolbar=no"}var f=window.open(b,d,attributes);f.focus()}function b_togglebox(a,b){jQuery("#"+a).slideToggle(400,function(){var c=jQuery(b);c.toggleClass("b_togglebox_closed");c.toggleClass("b_togglebox_opened")})}function b_handleFileUploadFormChange(e,b,d){var f=e.value;slashPos=f.lastIndexOf("/");if(slashPos!=-1){f=f.substring(slashPos+1)}slashPos=f.lastIndexOf("\\");if(slashPos!=-1){f=f.substring(slashPos+1)}b.value=f;if(d){d.className="b_button b_button_dirty"}var c=e.form.elements;for(i=0;i<c.length;i++){var a=c[i];if(a.name==b.name&&i+1<c.length){c[i+1].focus()}}}function gotonode(a){try{if(typeof o_activateCourseNode!="undefined"){o_activateCourseNode(a)}else{if(opener&&typeof opener.o_activateCourseNode!="undefined"){opener.o_activateCourseNode(a)}else{if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","Error in gotonode(), could not find main window","functions.js")}}}}catch(b){alert("Goto node error:"+b);if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","Error in gotonode()::"+b.message,"functions.js")}}}function o_openUriInMainWindow(b){try{var a=o_getMainWin();a.focus();a.location.replace(b)}catch(c){showMessageBox("error","Error","Can not find main OpenOLAT window to open URL.")}}function b_viewportHeight(){var a=jQuery(document).height();if(a>0){return a}else{return 600}}OPOL.getMainColumnsMaxHeight=function(){var j=0,f=0,a=0,c=0,h=0,b,g=jQuery("#b_col1_content"),e=jQuery("#b_col2_content"),d=jQuery("#b_col3_content");if(g!="undefined"&&g!=null){j=g.height()}if(e!="undefined"&&e!=null){f=e.height()}if(d!="undefined"&&d!=null){a=d.height()}c=(j>f?j:f);c=(c>a?c:a);if(c>0){return c}b=jQuery("#b_main");if(b!="undefined"&&b!=null){h=b.height()}if(b>0){return b}return b_viewportHeight()};function b_resizeIframeToMainMaxHeight(f){var d=jQuery("#"+f);if(d!="undefined"&&d!=null){var c=OPOL.getMainColumnsMaxHeight();var b=b_viewportHeight()-100;var e=jQuery("#b_header");if(e!="undefined"&&e!=null){b=b-e.height()}e=jQuery("#b_nav");if(e!="undefined"&&e!=null){b=b-e.height()}e=jQuery("#b_footer");if(e!="undefined"&&e!=null){b=b-e.height()}var a=(b>c?b:c);d.height(a)}}var o_debu_oldcn,o_debu_oldtt;function o_debu_show(b,a){if(o_debu_oldcn){o_debu_hide(o_debu_oldcn,o_debu_oldtt)}jQuery(b).css("border","3px solid #00F").css("margin","0px").css("background-color","#FCFCB8");jQuery(a).show();o_debu_oldtt=a;o_debu_oldcn=b}function o_debu_hide(b,a){jQuery(a).hide();jQuery(b).css("border","1px dotted black").css("margin","2px").css("background-color","")}function o_dbg_mark(a){var b=jQuery("#"+a);if(b){b.css("background-color","#FCFCB8");b.css("border","3px solid #00F")}}function o_dbg_unmark(a){var b=jQuery("#"+a);if(b){b.css("border","");b.css("background-color","")}}function o_clearConsole(){o_log_all="";o_log(null)}var o_log_all="";function o_log(b){if(b){o_log_all="\n"+o_debug_trid+"> "+b+o_log_all;o_log_all=o_log_all.substr(0,4000)}var a=jQuery("#o_debug_cons");if(a){if(o_log_all.length==4000){o_log_all=o_log_all+"\n... (stripped: to long)... "}a.value=o_log_all}if(!jQuery.browser.IE&&!jQuery.type(window.console)==="undefined"){window.console.log(b)}}function o_logerr(a){o_log("ERROR:"+a)}function o_logwarn(a){o_log("WARN:"+a)}function showerror(c){var a="";for(var b in c){a+=b+": "+c[b]+"\n"}return"error detail:\n"+a}function o_ffEvent(e,d,c,h,j){var f,g,b,a;f=document.getElementById(d);g=f.value;f.value=c;b=document.getElementById(h);a=b.value;b.value=j;if(document.forms[e].onsubmit()){document.forms[e].submit()}f.value=g;b.value=a}function o_ffXHREvent(f,e,a,h,j){var c=new Object();c.dispatchuri=a;c.dispatchevent=j;if(arguments.length>5){var g=arguments.length;for(var d=5;d<g;d=d+2){if(g>d+1){c[arguments[d]]=arguments[d+1]}}}var b=jQuery("#"+f).attr("action");jQuery.ajax(b,{type:"GET",data:c,dataType:"json",success:function(n,o,m){o_ainvoke(n)},error:function(m,o,n){if(console){console.log("Error status",o)}}})}function setFlexiFormDirtyByListener(a){setFlexiFormDirty(a.data.formId)}function setFlexiFormDirty(b){var a=o3c.indexOf(b)>-1;if(!a){o3c.push(b)}jQuery("#"+b).each(function(){var c=jQuery(this).data("FlexiSubmit");if(c!=null){jQuery("#"+c).addClass("b_button b_button_dirty");o2c=1}})}function o_ffRegisterSubmit(b,a){jQuery("#"+b).data("FlexiSubmit",a)}function showInfoBox(f,c){var b=Math.floor(Math.random()*65536).toString(16);var e='<div id="'+b+'" class="b_msg-div msg" style="display:none;"><div class="b_msg_info_content b_msg_info_winicon o_sel_info_message"><h3>'+f+"</h3>"+c+"<br/><br/></div></div>";var a=jQuery("#b_page").prepend(e);var d=(c.length>150)?8000:((c.length>70)?6000:4000);jQuery("#"+b).slideDown(300).delay(d).slideUp(300);jQuery("#"+b).click(function(g){jQuery("#"+b).remove()});f=null;c=null;a=null;d=null}function showMessageBox(b,e,c,a){if(b=="info"){showInfoBox(e,c);return null}else{var d;if("warn"==b){d='<div><div class="b_msg_info_content b_msg_warn_winicon">'}else{if("error"==b){d='<div><div class="b_msg_info_content b_msg_error_winicon">'}else{d="<div><div>"}}return jQuery(d+"<p>"+c+"</p></div></div>").dialog({height:170,width:400,modal:true,title:e,resizable:false,close:function(f,g){try{jQuery(this).dialog("destroy").remove()}catch(h){}}}).dialog("open")}}function tableFormInjectCommandAndSubmit(a,b,c){document.forms[a].elements.cmd.value=b;document.forms[a].elements.param.value=c;document.forms[a].submit()}function b_table_toggleCheck(d,c){var a=document.forms[d].elements.tb_ms;len=a.length;if(typeof(len)=="undefined"){a.checked=c}else{var b;for(b=0;b<len;b++){a[b].checked=c}}}function onTreeStartDrag(a,b){jQuery(a.target).addClass("b_dd_proxy")}function onTreeStopDrag(a,b){jQuery(a.target).removeClass("b_dd_proxy")}function onTreeDrop(g,h){var a=jQuery(h.draggable[0]);var f=jQuery(this);f.css({position:"",width:""});var c=f.droppable("option","endUrl");if(c.lastIndexOf("/")==(c.length-1)){c=c.substring(0,c.length-1)}var e=a.attr("id");var b=e.substring(2,e.length);c+="%3Atnidle%3A"+b;var d=f.attr("id");if(d.indexOf("ds")==0){c+="%3Asne%3Ayes"}else{if(d.indexOf("dt")==0){c+="%3Asne%3Aend"}}frames.oaa0.location.href=c+"/"}function treeAcceptDrop(b){var c=jQuery(b);var e=c.attr("id");if(e!=undefined&&(e.indexOf("dd")==0||e.indexOf("ds")==0||e.indexOf("dt")==0||e.indexOf("da")==0||e.indexOf("row")==0)){var g=jQuery(this);var j=g.attr("id");var d=e.substring(2,e.length);var f=j.substring(2,j.length);if(d==f){return false}var h="";if(j.indexOf("ds")==0){h="yes"}else{if(j.indexOf("dt")==0){h="end"}}var m=g.data(d+"-"+h);if(m===undefined){var a=g.droppable("option","fbUrl");jQuery.ajax(a,{async:false,data:{nidle:d,tnidle:f,sne:h},dataType:"json",method:"GET",success:function(n){m=n.dropAllowed}});g.data(d+"-"+h,m)}return m}return false}function b_choice_toggleCheck(c,b){var d=document.forms[c].elements;len=d.length;if(typeof(len)=="undefined"){d.checked=b}else{var a;for(a=0;a<len;a++){if(d[a].type=="checkbox"&&d[a].getAttribute("class")=="b_checkbox"){d[a].checked=b}}}}function b_briefcase_isChecked(c,e){var b;var a=document.getElementById(c);var d=0;for(b=0;a.elements[b];b++){if(a.elements[b].type=="checkbox"&&a.elements[b].name=="paths"&&a.elements[b].checked){d++}}if(d<1){alert(e);return false}return true}function b_briefcase_toggleCheck(d,c){var a=document.getElementById(d);len=a.elements.length;var b;for(b=0;b<len;b++){if(a.elements[b].name=="paths"){a.elements[b].checked=c}}}function b_doPrint(){var d=jQuery("div.b_iframe_wrapper iframe");if(d.length>0){try{var a=d[0];frames[a.name].focus();frames[a.name].print();return}catch(c){for(i=0;frames.length>i;i++){a=frames[i];if(a.name=="oaa0"){continue}var b=document.getElementsByName(a.name)[0];if(b&&b.getAttribute("class")=="ext-shim"){continue}if(a.name!=""){try{frames[a.name].focus();frames[a.name].print()}catch(c){window.print()}return}}window.print()}}else{window.print()}}function b_attach_i18n_inline_editing(){jQuery("span.b_translation_i18nitem").hover(function(){jQuery(this.firstChild).show();if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","Entered i18nitem::"+this.firstChild,"functions.js:b_attach_i18n_inline_editing()")}},function(){jQuery("a.b_translation_i18nitem_launcher").hide();if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","Leaving i18nitem::"+this,"functions.js:b_attach_i18n_inline_editing()")}});jQuery("a.b_translation_i18nitem_launcher").hover(function(){var a=jQuery(this).parent("span.b_translation_i18nitem");a.effect("highlight")});b_AddOnDomReplacementFinishedCallback(b_attach_i18n_inline_editing)}var BDebugger={_lastDOMCount:0,_lastObjCount:0,_knownGlobalOLATObjects:["o_afterserver","o_onc","o_getMainWin","o_ainvoke","o_info","o_beforeserver","o_ffEvent","o_openPopUp","o_debu_show","o_logwarn","o_dbg_unmark","o_ffRegisterSubmit","o_clearConsole","o_init","o_log","o_allowNextClick","o_dbg_mark","o_debu_hide","o_logerr","o_debu_oldcn","o_debu_oldtt","o_openUriInMainWindow","o_debug_trid","o_log_all"],_countDOMElements:function(){return document.getElementsByTagName("*").length},_countGlobalObjects:function(){var a=0;for(prop in window){a++}return a},logDOMCount:function(){var b=BDebugger;var a=b._countDOMElements();var c=a-b._lastDOMCount;console.log((c>0?"+":"")+c+" \t"+a+" \tDOM element count after DOM replacement");b._lastDOMCount=a;a=null},logGlobalObjCount:function(){var b=BDebugger;var a=b._countGlobalObjects();var c=a-b._lastObjCount;console.log((c>0?"+":"")+c+" \t"+a+" \tGlobal object count after DOM replacement");b._lastObjCount=a;a=null},logGlobalOLATObjects:function(){var b=BDebugger;var a=new Array();for(prop in window){if(prop.indexOf("o_")==0&&b._knownGlobalOLATObjects.indexOf(prop)==-1){a.push(prop)}}if(a.length>0){console.log(a.length+" global OLAT objects found:");a.each(function(c){console.log("\t"+typeof window[c]+" \t"+c)})}},logManagedOLATObjects:function(){var a=BDebugger;if(o_info.objectMap.length>0){console.log(o_info.objectMap.length+" managed OLAT objects found:");o_info.objectMap.eachKey(function(b){var c=o_info.objectMap.get(b);console.log("\t"+typeof c+" \t"+b);return true})}}};var Hashtable=(function(){var p="function";var n=(typeof Array.prototype.splice==p)?function(s,r){s.splice(r,1)}:function(u,t){var s,v,r;if(t===u.length-1){u.length=t}else{s=u.slice(t+1);u.length=t;for(v=0,r=s.length;v<r;++v){u[t+v]=s[v]}}};function a(t){var r;if(typeof t=="string"){return t}else{if(typeof t.hashCode==p){r=t.hashCode();return(typeof r=="string")?r:a(r)}else{if(typeof t.toString==p){return t.toString()}else{try{return String(t)}catch(s){return Object.prototype.toString.call(t)}}}}}function g(r,s){return r.equals(s)}function e(r,s){return(typeof s.equals==p)?s.equals(r):(r===s)}function c(r){return function(s){if(s===null){throw new Error("null is not a valid "+r)}else{if(typeof s=="undefined"){throw new Error(r+" must not be undefined")}}}}var q=c("key"),l=c("value");function d(u,s,t,r){this[0]=u;this.entries=[];this.addEntry(s,t);if(r!==null){this.getEqualityFunction=function(){return r}}}var h=0,j=1,f=2;function o(r){return function(t){var s=this.entries.length,v,u=this.getEqualityFunction(t);while(s--){v=this.entries[s];if(u(t,v[0])){switch(r){case h:return true;case j:return v;case f:return[s,v[1]]}}}return false}}function k(r){return function(u){var v=u.length;for(var t=0,s=this.entries.length;t<s;++t){u[v+t]=this.entries[t][r]}}}d.prototype={getEqualityFunction:function(r){return(typeof r.equals==p)?g:e},getEntryForKey:o(j),getEntryAndIndexForKey:o(f),removeEntryForKey:function(s){var r=this.getEntryAndIndexForKey(s);if(r){n(this.entries,r[0]);return r[1]}return null},addEntry:function(r,s){this.entries[this.entries.length]=[r,s]},keys:k(0),values:k(1),getEntries:function(s){var u=s.length;for(var t=0,r=this.entries.length;t<r;++t){s[u+t]=this.entries[t].slice(0)}},containsKey:o(h),containsValue:function(s){var r=this.entries.length;while(r--){if(s===this.entries[r][1]){return true}}return false}};function m(s,t){var r=s.length,u;while(r--){u=s[r];if(t===u[0]){return r}}return null}function i(r,s){var t=r[s];return(t&&(t instanceof d))?t:null}function b(t,r){var w=this;var v=[];var u={};var x=(typeof t==p)?t:a;var s=(typeof r==p)?r:null;this.put=function(B,C){q(B);l(C);var D=x(B),E,A,z=null;E=i(u,D);if(E){A=E.getEntryForKey(B);if(A){z=A[1];A[1]=C}else{E.addEntry(B,C)}}else{E=new d(D,B,C,s);v[v.length]=E;u[D]=E}return z};this.get=function(A){q(A);var B=x(A);var C=i(u,B);if(C){var z=C.getEntryForKey(A);if(z){return z[1]}}return null};this.containsKey=function(A){q(A);var z=x(A);var B=i(u,z);return B?B.containsKey(A):false};this.containsValue=function(A){l(A);var z=v.length;while(z--){if(v[z].containsValue(A)){return true}}return false};this.clear=function(){v.length=0;u={}};this.isEmpty=function(){return !v.length};var y=function(z){return function(){var A=[],B=v.length;while(B--){v[B][z](A)}return A}};this.keys=y("keys");this.values=y("values");this.entries=y("getEntries");this.remove=function(B){q(B);var C=x(B),z,A=null;var D=i(u,C);if(D){A=D.removeEntryForKey(B);if(A!==null){if(!D.entries.length){z=m(v,C);n(v,z);delete u[C]}}}return A};this.size=function(){var A=0,z=v.length;while(z--){A+=v[z].entries.length}return A};this.each=function(C){var z=w.entries(),A=z.length,B;while(A--){B=z[A];C(B[0],B[1])}};this.putAll=function(H,C){var B=H.entries();var E,F,D,z,A=B.length;var G=(typeof C==p);while(A--){E=B[A];F=E[0];D=E[1];if(G&&(z=w.get(F))){D=C(F,z,D)}w.put(F,D)}};this.clone=function(){var z=new b(t,r);z.putAll(w);return z}}return b})();(function(b){b.fn.ooLog=function(f,d,e){var c=null;b(this).each(function(){c=b(this).data("_ooLog");if(c==undefined){c=new a();b(this).data("_ooLog",c)}});if(f==undefined){return c}else{if(typeof f==="string"){if(c){c.log(f,d,e)}}}};function a(){return this}a.prototype={isDebugEnabled:function(){return o_info.JSTracingLogDebugEnabled},log:function(e,c,d){if(!this.isDebugEnabled()){return}jQuery.post(o_info.JSTracingUri,{level:e,logMsg:c,jsFile:d})}}})(jQuery);(function(b){b.fn.ooTranslator=function(){var d=null;b(document).each(function(){d=b(document).data("_ooTranslator");if(d==undefined){d=new a();b(document).data("_ooTranslator",d)}});return d};function a(){return this}a.prototype={mapperUrl:null,translators:null,initialize:function(d){this.mapperUrl=d;this.translators=new Object()},getTranslator:function(d,f){if(this.translators[d]==null){this.translators[d]=new Object()}if(this.translators[d][f]==null){var e=this.mapperUrl+"/"+d+"/"+f+"/translations.js";jQuery.ajax(e,{async:false,dataType:"json",success:function(g,i,h){jQuery(document).ooTranslator()._createTranslator(g,d,f)}})}return this.translators[d][f]},_createTranslator:function(e,d,f){this.translators[d][f]=new c().initialize(e,d,f)}};function c(){return this}c.prototype={localizationData:null,bundle:null,locale:null,initialize:function(f,d,e){this.bundle=e;this.locale=d;this.localizationData=f;return this},translate:function(d){if(this.localizationData[d]){return this.localizationData[d]}else{return this.bundle+":"+d}}}})(jQuery);/*! +OPOL={};var o2c=0;var o3c=new Array();o_info.guibusy=false;o_info.linkbusy=false;o_info.debug=true;var BLoader={_ajaxLoadedJS:new Array(),_isAlreadyLoadedJS:function(b){var a=true;jQuery("head script[src]").each(function(d,c){if(jQuery(c).attr("src").indexOf(b)!=-1){a=false}});if(jQuery.inArray(b,this._ajaxLoadedJS)!=-1){a=false}return !a},loadJS:function(b,c,a){if(!this._isAlreadyLoadedJS(b)){if(o_info.debug){o_log("BLoader::loadJS: loading ajax::"+a+" url::"+b)}if(a){jQuery.ajax(b,{async:false,dataType:"script",success:function(d,f,e){}});this._ajaxLoadedJS.push(b)}else{jQuery.getScript(b)}if(o_info.debug){o_log("BLoader::loadJS: loading DONE url::"+b)}}else{if(o_info.debug){o_log("BLoader::loadJS: already loaded url::"+b)}}},executeGlobalJS:function(jsString,contextDesc){try{if(window.execScript){window.execScript(jsString)}else{window.eval(jsString)}}catch(e){if(console){console.log(contextDesc,"cannot execute js",jsString)}if(o_info.debug){o_logerr("BLoader::executeGlobalJS: Error when executing JS code in contextDesc::"+contextDesc+' error::"'+showerror(e)+" for: "+escape(jsString))}if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","BLoader::executeGlobalJS: Error when executing JS code in contextDesc::"+contextDesc+' error::"'+showerror(e)+" for: "+escape(jsString),"functions.js::BLoader::executeGlobalJS::"+contextDesc)}if(window.location.href.indexOf("o_winrndo")!=-1){window.location.reload()}else{window.location.href=window.location.href+(window.location.href.indexOf("?")!=-1?"&":"?")+"o_winrndo=1"}}},loadCSS:function(b,o,q){var r=window.document;try{if(r.createStyleSheet){var j=r.styleSheets;var d=0;var p=0;for(i=0;i<j.length;i++){var m=j[i];var g=m.href;if(g==b){d++;if(m.disabled){m.disabled=false;return}else{if(o_info.debug){o_logwarn("BLoader::loadCSS: style: "+b+" already in document and not disabled! (duplicate add)")}return}}if(m.id=="b_theme_css"){p=i}}if(d>1&&o_info.debug){o_logwarn("BLoader::loadCSS: apply styles: num of stylesheets found was not 0 or 1:"+d)}if(q){p=j.length}var f=r.createStyleSheet(b,p)}else{var c=jQuery("#"+o);if(c&&c.size()>0){if(o_info.debug){o_logwarn("BLoader::loadCSS: stylesheet already found in doc when trying to add:"+b+", with id "+o)}return}else{var a=jQuery('<link id="'+o+'" rel="stylesheet" type="text/css" href="'+b+'">');if(q){a.insertBefore(jQuery("#b_fontSize_css"))}else{a.insertBefore(jQuery("#b_theme_css"))}}}}catch(n){if(console){console.log(n)}if(o_info.debug){o_logerr("BLoader::loadCSS: Error when loading CSS from URL::"+b)}if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","BLoader::loadCSS: Error when loading CSS from URL::"+b,"functions.js::BLoader::loadCSS")}}},unLoadCSS:function(a,m){var n=window.document;try{if(n.createStyleSheet){var f=n.styleSheets;var d=0;var o=a;var b=window.location.href.substring(0,window.location.href.indexOf("/",8));if(a.indexOf(b)==0){o=a.substring(b.length)}for(i=0;i<f.length;i++){var g=f[i].href;if(g==a||g==o){d++;if(!f[i].disabled){f[i].disabled=true}else{if(o_info.debug){o_logwarn("stylesheet: when removing: matching url, but already disabled! url:"+g)}}}}if(d!=1&&o_info.debug){o_logwarn("stylesheet: when removeing: num of stylesheets found was not 1:"+d)}}else{var c=jQuery("#"+m);if(c){c.href="";c.remove();c=null;return}else{if(o_info.debug){o_logwarn("no link with id found to remove, id:"+m+", url "+a)}}}}catch(j){if(o_info.debug){o_logerr("BLoader::unLoadCSS: Error when unloading CSS from URL::"+a)}if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","BLoader::unLoadCSS: Error when unloading CSS from URL::"+a,"functions.js::BLoader::loadCSS")}}}};var BFormatter={formatLatexFormulas:function(b){try{if(jsMath){if(jsMath.loaded){jsMath.ProcessBeforeShowing.curry(b).delay(0.01)}else{jsMath.Autoload.LoadJsMath();BFormatter.formatLatexFormulas.delay(0.1)}}else{if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","BFormatter::formatLatexFormulas: can not format latex formulas, jsMath not installed. Check your logfile","functions.js::BFormatter::formatLatexFormulas")}}}catch(a){if(o_info.debug){o_log("error in BFormatter.formatLatexFormulas: "+showerror(a))}}}};function o_init(){try{o_getMainWin().o_afterserver()}catch(a){if(o_info.debug){o_log("error in o_init: "+showerror(a))}}}function b_initEmPxFactor(){o_info.emPxFactor=jQuery("#b_width_1em").width();if(o_info.emPxFactor==0||o_info.emPxFactor=="undefined"){o_info.emPxFactor=12;if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","Could not read with of element b_width_1em, set o_info.emPxFactor to 12","functions.js")}}}function o_getMainWin(){try{if(window.opener&&window.opener.OPOL){return window.opener}else{if(window.OPOL){return window}}}catch(a){if(o_info.debug){o_logerr('Exception while getting main window. rror::"'+showerror(a))}if(B_AjaxLogger.isDebugEnabled()){B_AjaxLogger.logDebug('Exception while getting main window. rror::"'+showerror(a),"functions.js")}}throw"Can not find main OpenOLAT window"}function o_beforeserver(){o_info.linkbusy=true;showAjaxBusy();if(window.suppressOlatOnUnloadOnce){window.suppressOlatOnUnloadOnce=false}else{if(window.olatonunload){olatonunload()}}}function o_afterserver(){o2c=0;o_info.linkbusy=false;removeAjaxBusy()}function o2cl(){if(o_info.linkbusy){return false}else{var a=(o2c==0||confirm(o_info.dirty_form));if(a){o_beforeserver()}return a}}function o3cl(d){if(o_info.linkbusy){return false}else{var b=o3c1.indexOf(d)>-1;var a=(b&&o3c1.length>1)||o3c1.length>0;var c=(!a||confirm(o_info.dirty_form));if(c){o_beforeserver()}return c}}function o_onc(a){var b=a.responseText;BLoader.executeGlobalJS("o_info.last_o_onc="+b+";","o_onc");o_ainvoke(o_info.last_o_onc,false)}function o_allowNextClick(){o_info.linkbusy=false;removeAjaxBusy()}function removeBusyAfterDownload(c,b,a){o2c=0;o_afterserver()}Array.prototype.search=function(c,d){var a=this.length;for(var b=0;b<a;b++){if(this[b].constructor==Array){if(this[b].search(c,d)){return true;break}}else{if(d){if(this[b].indexOf(c)!=-1){return true;break}}else{if(this[b]==c){return true;break}}}}return false};if(!Function.prototype.curry){Function.prototype.curry=function(){if(arguments.length<1){return this}var a=this;var b=Array.prototype.slice.call(arguments);return function(){return a.apply(this,b.concat(Array.prototype.slice.call(arguments)))}}}if(!Array.prototype.indexOf){Array.prototype.indexOf=function(c){if(this==null){throw new TypeError()}var d=Object(this);var a=d.length>>>0;if(a===0){return -1}var e=0;if(arguments.length>1){e=Number(arguments[1]);if(e!=e){e=0}else{if(e!=0&&e!=Infinity&&e!=-Infinity){e=(e>0||-1)*Math.floor(Math.abs(e))}}}if(e>=a){return -1}var b=e>=0?e:Math.max(a-Math.abs(e),0);for(;b<a;b++){if(b in d&&d[b]===c){return b}}return -1}}var b_onDomReplacementFinished_callbacks=new Array();function b_AddOnDomReplacementFinishedCallback(a){var b=jQuery(document).ooLog().isDebugEnabled();if(b){jQuery(document).ooLog("debug","callback stack size: "+b_onDomReplacementFinished_callbacks.length,"functions.js ADD")}if(b&&jQuery.browser.mozilla&&!jQuery.browser.webkit){jQuery(document).ooLog("debug","stack content"+b_onDomReplacementFinished_callbacks.toSource(),"functions.js ADD")}b_onDomReplacementFinished_callbacks.push(a);if(b){jQuery(document).ooLog("debug","push to callback stack, func: "+a,"functions.js ADD")}}var b_changedDomEl=new Array();function b_AddOnDomReplacementFinishedUniqueCallback(a){if(a.constructor==Array){if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","add: its an ARRAY! ","functions.js ADD")}if(b_onDomReplacementFinished_callbacks.search(a[0])){if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","push to callback stack, already there!!: "+a[0],"functions.js ADD")}return}}b_AddOnDomReplacementFinishedCallback(a)}var o_debug_trid=0;function o_ainvoke(H){if(H==undefined){return}o_info.inainvoke=true;var D=H.cmdcnt;if(D>0){b_changedDomEl=new Array();if(o_info.debug){o_debug_trid++}var v=H.cmds;for(var N=0;N<D;N++){var E=v[N];var x=E.cmd;var L=E.cda;var O=E.w;var b=this.window;var F;if(b){switch(x){case 1:var G=L.e;BLoader.executeGlobalJS(G,"o_ainvoker::jsexec");if(o_info.debug){o_log("c1: execute jscode: "+G)}case 2:var s=L.cc;var B=L.cps;for(var K=0;K<s;K++){var h=B[K];var g=h.cid;var J=h.cidvis;var u=h.hfrag;var I=h.jsol;var f=h.hdr;if(o_info.debug){o_log("c2: redraw: "+h.cname+" ("+g+") "+h.hfragsize+" bytes, listener(s): "+h.clisteners)}var Q=f+"\n\n"+u;var z="";var M=false;var y=jQuery("#o_c"+g);if(y==null||(y.length==0)){y=jQuery("#o_fi"+g);M=true}if(y!=null){if(J){y.css("display","")}else{y.css("display","none")}if(M){y.replaceWith(Q)}else{y.empty();try{y.html(Q)}catch(T){if(console){console.log(T)}if(console){console.log("Fragment",Q)}}b_changedDomEl.push("o_c"+g)}y=null;if(z!=""){z.each(function(e){BLoader.executeGlobalJS(e,"o_ainvoker::inscripts")})}if(I!=""){BLoader.executeGlobalJS(I,"o_ainvoker::jsol")}}}break;case 3:b.o2c=0;var R=L.rurl;b.o_afterserver();b.document.location.replace(R);break;case 5:b.o2c=0;var R=L.rurl;b.o_afterserver();b.document.location.replace(R);break;case 6:b.o2c=0;b.o_afterserver();break;case 7:var n=b.document.location;var w=n.protocol+"//"+n.hostname;if(n.port!=""){w+=":"+n.port}var t=L.cssrm;for(K=0;K<t.length;K++){var A=t[K];var C=A.id;var d=w+A.url;BLoader.unLoadCSS(d,C);if(o_info.debug){o_log("c7: rm css: id:"+C+" ,url:'"+d+"'")}}var P=L.cssadd;for(k=0;k<P.length;k++){var A=P[k];var C=A.id;var d=w+A.url;var m=A.pt;BLoader.loadCSS(d,C,m);if(o_info.debug){o_log("c7: add css: id:"+C+" ,url:'"+d+"'")}}var o=L.jsadd;for(l=0;l<o.length;l++){var A=o[l];var S=A.before;if(jQuery.type(S)==="string"){BLoader.executeGlobalJS(S,"o_ainvoker::preJsAdd")}var d=A.url;var p=A.enc;if(jQuery.type(d)==="string"){BLoader.loadJS(d,p,true)}if(o_info.debug){o_log("c7: add js: "+d)}}break;default:if(o_info.debug){o_log("?: unknown command "+x)}if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","Error in o_ainvoke(), ?: unknown command "+x,"functions.js")}break}}else{if(o_info.debug){o_log("could not find window??")}if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","Error in o_ainvoke(), could not find window??","functions.js")}}}var a=b_onDomReplacementFinished_callbacks.length;if(jQuery.browser.mozilla&&!jQuery.browser.webkit){if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","stack content"+b_onDomReplacementFinished_callbacks.toSource(),"functions.js")}}for(mycounter=0;a>mycounter;mycounter++){if(mycounter>50){if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","Stopped executing DOM replacement callback functions - to many functions::"+b_onDomReplacementFinished_callbacks.length,"functions.js")}break}if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","Stacksize before shift: "+b_onDomReplacementFinished_callbacks.length,"functions.js")}var q=b_onDomReplacementFinished_callbacks.shift();if(typeof q.length==="number"){if(q[0]=="glosshighlighter"){var c=q[1];if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","arr fct: "+c,"functions.js")}q=c}}if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","Executing DOM replacement callback function #"+mycounter+" with timeout funct::"+q,"functions.js")}q();if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","Stacksize after timeout: "+b_onDomReplacementFinished_callbacks.length,"functions.js")}}}o_info.inainvoke=false}function clearAfterAjaxIframeCall(){if(o_info.linkbusy){o_afterserver();showMessageBox("info",o_info.i18n_noresponse_title,o_info.i18n_noresponse,undefined)}}function showAjaxBusy(){if(o_info.linkbusy){try{jQuery("#b_ajax_busy").delay(500).queue(function(b){jQuery(this).addClass("b_ajax_busy");jQuery("#b_body").addClass("b_ajax_busy")})}catch(a){}}return}function removeAjaxBusy(){try{jQuery("#b_ajax_busy").delay(500).queue(function(b){jQuery(this).removeClass("b_ajax_busy");jQuery("#b_body").removeClass("b_ajax_busy")})}catch(a){}}var htmlEditorEnabled=(jQuery.browser.msie||jQuery.browser.mozilla);var scormPlayerEnabled=(jQuery.browser.msie||jQuery.browser.mozilla||jQuery.browser.webkit);function setFormDirty(c){o2c=1;var a=document.getElementById(c);if(a!=null){var b=a.olat_fosm_0;if(b==null){b=a.olat_fosm}if(b){b.className="b_button b_button_dirty"}}else{if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","Error in setFormDirty, myForm was null for formId="+c,"functions.js")}}}function contextHelpWindow(a){helpWindow=window.open(a,"HelpWindow","height=760, width=940, left=0, top=0, location=no, menubar=no, resizable=yes, scrollbars=yes, toolbar=no");helpWindow.focus()}function o_openPopUp(b,d,c,a,e){attributes="height="+a+", width="+c+", resizable=yes, scrollbars=yes, left=100, top=100, ";if(e){attributes+="location=yes, menubar=yes, status=yes, toolbar=yes"}else{attributes+="location=no, menubar=no, status=no, toolbar=no"}var f=window.open(b,d,attributes);f.focus()}function b_togglebox(a,b){jQuery("#"+a).slideToggle(400,function(){var c=jQuery(b);c.toggleClass("b_togglebox_closed");c.toggleClass("b_togglebox_opened")})}function b_handleFileUploadFormChange(e,b,d){var f=e.value;slashPos=f.lastIndexOf("/");if(slashPos!=-1){f=f.substring(slashPos+1)}slashPos=f.lastIndexOf("\\");if(slashPos!=-1){f=f.substring(slashPos+1)}b.value=f;if(d){d.className="b_button b_button_dirty"}var c=e.form.elements;for(i=0;i<c.length;i++){var a=c[i];if(a.name==b.name&&i+1<c.length){c[i+1].focus()}}}function gotonode(a){try{if(typeof o_activateCourseNode!="undefined"){o_activateCourseNode(a)}else{if(opener&&typeof opener.o_activateCourseNode!="undefined"){opener.o_activateCourseNode(a)}else{if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","Error in gotonode(), could not find main window","functions.js")}}}}catch(b){alert("Goto node error:"+b);if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","Error in gotonode()::"+b.message,"functions.js")}}}function o_openUriInMainWindow(b){try{var a=o_getMainWin();a.focus();a.location.replace(b)}catch(c){showMessageBox("error","Error","Can not find main OpenOLAT window to open URL.")}}function b_viewportHeight(){var a=jQuery(document).height();if(a>0){return a}else{return 600}}OPOL.getMainColumnsMaxHeight=function(){var j=0,f=0,a=0,c=0,h=0,b,g=jQuery("#b_col1_content"),e=jQuery("#b_col2_content"),d=jQuery("#b_col3_content");if(g!="undefined"&&g!=null){j=g.height()}if(e!="undefined"&&e!=null){f=e.height()}if(d!="undefined"&&d!=null){a=d.height()}c=(j>f?j:f);c=(c>a?c:a);if(c>0){return c}b=jQuery("#b_main");if(b!="undefined"&&b!=null){h=b.height()}if(b>0){return b}return b_viewportHeight()};function b_resizeIframeToMainMaxHeight(f){var d=jQuery("#"+f);if(d!="undefined"&&d!=null){var c=OPOL.getMainColumnsMaxHeight();var b=b_viewportHeight()-100;var e=jQuery("#b_header");if(e!="undefined"&&e!=null){b=b-e.height()}e=jQuery("#b_nav");if(e!="undefined"&&e!=null){b=b-e.height()}e=jQuery("#b_footer");if(e!="undefined"&&e!=null){b=b-e.height()}var a=(b>c?b:c);d.height(a)}}var o_debu_oldcn,o_debu_oldtt;function o_debu_show(b,a){if(o_debu_oldcn){o_debu_hide(o_debu_oldcn,o_debu_oldtt)}jQuery(b).css("border","3px solid #00F").css("margin","0px").css("background-color","#FCFCB8");jQuery(a).show();o_debu_oldtt=a;o_debu_oldcn=b}function o_debu_hide(b,a){jQuery(a).hide();jQuery(b).css("border","1px dotted black").css("margin","2px").css("background-color","")}function o_dbg_mark(a){var b=jQuery("#"+a);if(b){b.css("background-color","#FCFCB8");b.css("border","3px solid #00F")}}function o_dbg_unmark(a){var b=jQuery("#"+a);if(b){b.css("border","");b.css("background-color","")}}function o_clearConsole(){o_log_all="";o_log(null)}var o_log_all="";function o_log(b){if(b){o_log_all="\n"+o_debug_trid+"> "+b+o_log_all;o_log_all=o_log_all.substr(0,4000)}var a=jQuery("#o_debug_cons");if(a){if(o_log_all.length==4000){o_log_all=o_log_all+"\n... (stripped: to long)... "}a.value=o_log_all}if(!jQuery.browser.IE&&!jQuery.type(window.console)==="undefined"){window.console.log(b)}}function o_logerr(a){o_log("ERROR:"+a)}function o_logwarn(a){o_log("WARN:"+a)}function showerror(c){var a="";for(var b in c){a+=b+": "+c[b]+"\n"}return"error detail:\n"+a}function o_ffEvent(e,d,c,h,j){var f,g,b,a;f=document.getElementById(d);g=f.value;f.value=c;b=document.getElementById(h);a=b.value;b.value=j;if(document.forms[e].onsubmit()){document.forms[e].submit()}f.value=g;b.value=a}function o_ffXHREvent(f,e,a,h,j){var c=new Object();c.dispatchuri=a;c.dispatchevent=j;if(arguments.length>5){var g=arguments.length;for(var d=5;d<g;d=d+2){if(g>d+1){c[arguments[d]]=arguments[d+1]}}}var b=jQuery("#"+f).attr("action");jQuery.ajax(b,{type:"GET",data:c,dataType:"json",success:function(n,o,m){o_ainvoke(n)},error:function(m,o,n){if(console){console.log("Error status",o)}}})}function setFlexiFormDirtyByListener(a){setFlexiFormDirty(a.data.formId)}function setFlexiFormDirty(b){var a=o3c.indexOf(b)>-1;if(!a){o3c.push(b)}jQuery("#"+b).each(function(){var c=jQuery(this).data("FlexiSubmit");if(c!=null){jQuery("#"+c).addClass("b_button b_button_dirty");o2c=1}})}function o_ffRegisterSubmit(b,a){jQuery("#"+b).data("FlexiSubmit",a)}function showInfoBox(f,c){var b=Math.floor(Math.random()*65536).toString(16);var e='<div id="'+b+'" class="b_msg-div msg" style="display:none;"><div class="b_msg_info_content b_msg_info_winicon o_sel_info_message"><h3>'+f+"</h3>"+c+"<br/><br/></div></div>";var a=jQuery("#b_page").prepend(e);var d=(c.length>150)?8000:((c.length>70)?6000:4000);jQuery("#"+b).slideDown(300).delay(d).slideUp(300);jQuery("#"+b).click(function(g){jQuery("#"+b).remove()});f=null;c=null;a=null;d=null}function showMessageBox(b,e,c,a){if(b=="info"){showInfoBox(e,c);return null}else{var d;if("warn"==b){d='<div><div class="b_msg_info_content b_msg_warn_winicon">'}else{if("error"==b){d='<div><div class="b_msg_info_content b_msg_error_winicon">'}else{d="<div><div>"}}return jQuery(d+"<p>"+c+"</p></div></div>").dialog({height:170,width:400,modal:true,title:e,resizable:false,close:function(f,g){try{jQuery(this).dialog("destroy").remove()}catch(h){}}}).dialog("open")}}function tableFormInjectCommandAndSubmit(a,b,c){document.forms[a].elements.cmd.value=b;document.forms[a].elements.param.value=c;document.forms[a].submit()}function b_table_toggleCheck(d,c){var a=document.forms[d].elements.tb_ms;len=a.length;if(typeof(len)=="undefined"){a.checked=c}else{var b;for(b=0;b<len;b++){a[b].checked=c}}}function onTreeStartDrag(a,b){jQuery(a.target).addClass("b_dd_proxy")}function onTreeStopDrag(a,b){jQuery(a.target).removeClass("b_dd_proxy")}function onTreeDrop(g,h){var a=jQuery(h.draggable[0]);var f=jQuery(this);f.css({position:"",width:""});var c=f.droppable("option","endUrl");if(c.lastIndexOf("/")==(c.length-1)){c=c.substring(0,c.length-1)}var e=a.attr("id");var b=e.substring(2,e.length);c+="%3Atnidle%3A"+b;var d=f.attr("id");if(d.indexOf("ds")==0){c+="%3Asne%3Ayes"}else{if(d.indexOf("dt")==0){c+="%3Asne%3Aend"}}frames.oaa0.location.href=c+"/"}function treeAcceptDrop(b){var c=jQuery(b);var e=c.attr("id");if(e!=undefined&&(e.indexOf("dd")==0||e.indexOf("ds")==0||e.indexOf("dt")==0||e.indexOf("da")==0||e.indexOf("row")==0)){var g=jQuery(this);var j=g.attr("id");var d=e.substring(2,e.length);var f=j.substring(2,j.length);if(d==f){return false}var h="";if(j.indexOf("ds")==0){h="yes"}else{if(j.indexOf("dt")==0){h="end"}}var m=g.data(d+"-"+h);if(m===undefined){var a=g.droppable("option","fbUrl");jQuery.ajax(a,{async:false,data:{nidle:d,tnidle:f,sne:h},dataType:"json",method:"GET",success:function(n){m=n.dropAllowed}});g.data(d+"-"+h,m)}return m}return false}function b_choice_toggleCheck(c,b){var d=document.forms[c].elements;len=d.length;if(typeof(len)=="undefined"){d.checked=b}else{var a;for(a=0;a<len;a++){if(d[a].type=="checkbox"&&d[a].getAttribute("class")=="b_checkbox"){d[a].checked=b}}}}function b_briefcase_isChecked(c,e){var b;var a=document.getElementById(c);var d=0;for(b=0;a.elements[b];b++){if(a.elements[b].type=="checkbox"&&a.elements[b].name=="paths"&&a.elements[b].checked){d++}}if(d<1){alert(e);return false}return true}function b_briefcase_toggleCheck(d,c){var a=document.getElementById(d);len=a.elements.length;var b;for(b=0;b<len;b++){if(a.elements[b].name=="paths"){a.elements[b].checked=c}}}function b_doPrint(){var d=jQuery("div.b_iframe_wrapper iframe");if(d.length>0){try{var a=d[0];frames[a.name].focus();frames[a.name].print();return}catch(c){for(i=0;frames.length>i;i++){a=frames[i];if(a.name=="oaa0"){continue}var b=document.getElementsByName(a.name)[0];if(b&&b.getAttribute("class")=="ext-shim"){continue}if(a.name!=""){try{frames[a.name].focus();frames[a.name].print()}catch(c){window.print()}return}}window.print()}}else{window.print()}}function b_attach_i18n_inline_editing(){jQuery("span.b_translation_i18nitem").hover(function(){jQuery(this.firstChild).show();if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","Entered i18nitem::"+this.firstChild,"functions.js:b_attach_i18n_inline_editing()")}},function(){jQuery("a.b_translation_i18nitem_launcher").hide();if(jQuery(document).ooLog().isDebugEnabled()){jQuery(document).ooLog("debug","Leaving i18nitem::"+this,"functions.js:b_attach_i18n_inline_editing()")}});jQuery("a.b_translation_i18nitem_launcher").hover(function(){var a=jQuery(this).parent("span.b_translation_i18nitem");a.effect("highlight")});b_AddOnDomReplacementFinishedCallback(b_attach_i18n_inline_editing)}var BDebugger={_lastDOMCount:0,_lastObjCount:0,_knownGlobalOLATObjects:["o_afterserver","o_onc","o_getMainWin","o_ainvoke","o_info","o_beforeserver","o_ffEvent","o_openPopUp","o_debu_show","o_logwarn","o_dbg_unmark","o_ffRegisterSubmit","o_clearConsole","o_init","o_log","o_allowNextClick","o_dbg_mark","o_debu_hide","o_logerr","o_debu_oldcn","o_debu_oldtt","o_openUriInMainWindow","o_debug_trid","o_log_all"],_countDOMElements:function(){return document.getElementsByTagName("*").length},_countGlobalObjects:function(){var a=0;for(prop in window){a++}return a},logDOMCount:function(){var b=BDebugger;var a=b._countDOMElements();var c=a-b._lastDOMCount;console.log((c>0?"+":"")+c+" \t"+a+" \tDOM element count after DOM replacement");b._lastDOMCount=a;a=null},logGlobalObjCount:function(){var b=BDebugger;var a=b._countGlobalObjects();var c=a-b._lastObjCount;console.log((c>0?"+":"")+c+" \t"+a+" \tGlobal object count after DOM replacement");b._lastObjCount=a;a=null},logGlobalOLATObjects:function(){var b=BDebugger;var a=new Array();for(prop in window){if(prop.indexOf("o_")==0&&b._knownGlobalOLATObjects.indexOf(prop)==-1){a.push(prop)}}if(a.length>0){console.log(a.length+" global OLAT objects found:");a.each(function(c){console.log("\t"+typeof window[c]+" \t"+c)})}},logManagedOLATObjects:function(){var a=BDebugger;if(o_info.objectMap.length>0){console.log(o_info.objectMap.length+" managed OLAT objects found:");o_info.objectMap.eachKey(function(b){var c=o_info.objectMap.get(b);console.log("\t"+typeof c+" \t"+b);return true})}}};var Hashtable=(function(){var p="function";var n=(typeof Array.prototype.splice==p)?function(s,r){s.splice(r,1)}:function(u,t){var s,v,r;if(t===u.length-1){u.length=t}else{s=u.slice(t+1);u.length=t;for(v=0,r=s.length;v<r;++v){u[t+v]=s[v]}}};function a(t){var r;if(typeof t=="string"){return t}else{if(typeof t.hashCode==p){r=t.hashCode();return(typeof r=="string")?r:a(r)}else{if(typeof t.toString==p){return t.toString()}else{try{return String(t)}catch(s){return Object.prototype.toString.call(t)}}}}}function g(r,s){return r.equals(s)}function e(r,s){return(typeof s.equals==p)?s.equals(r):(r===s)}function c(r){return function(s){if(s===null){throw new Error("null is not a valid "+r)}else{if(typeof s=="undefined"){throw new Error(r+" must not be undefined")}}}}var q=c("key"),l=c("value");function d(u,s,t,r){this[0]=u;this.entries=[];this.addEntry(s,t);if(r!==null){this.getEqualityFunction=function(){return r}}}var h=0,j=1,f=2;function o(r){return function(t){var s=this.entries.length,v,u=this.getEqualityFunction(t);while(s--){v=this.entries[s];if(u(t,v[0])){switch(r){case h:return true;case j:return v;case f:return[s,v[1]]}}}return false}}function k(r){return function(u){var v=u.length;for(var t=0,s=this.entries.length;t<s;++t){u[v+t]=this.entries[t][r]}}}d.prototype={getEqualityFunction:function(r){return(typeof r.equals==p)?g:e},getEntryForKey:o(j),getEntryAndIndexForKey:o(f),removeEntryForKey:function(s){var r=this.getEntryAndIndexForKey(s);if(r){n(this.entries,r[0]);return r[1]}return null},addEntry:function(r,s){this.entries[this.entries.length]=[r,s]},keys:k(0),values:k(1),getEntries:function(s){var u=s.length;for(var t=0,r=this.entries.length;t<r;++t){s[u+t]=this.entries[t].slice(0)}},containsKey:o(h),containsValue:function(s){var r=this.entries.length;while(r--){if(s===this.entries[r][1]){return true}}return false}};function m(s,t){var r=s.length,u;while(r--){u=s[r];if(t===u[0]){return r}}return null}function i(r,s){var t=r[s];return(t&&(t instanceof d))?t:null}function b(t,r){var w=this;var v=[];var u={};var x=(typeof t==p)?t:a;var s=(typeof r==p)?r:null;this.put=function(B,C){q(B);l(C);var D=x(B),E,A,z=null;E=i(u,D);if(E){A=E.getEntryForKey(B);if(A){z=A[1];A[1]=C}else{E.addEntry(B,C)}}else{E=new d(D,B,C,s);v[v.length]=E;u[D]=E}return z};this.get=function(A){q(A);var B=x(A);var C=i(u,B);if(C){var z=C.getEntryForKey(A);if(z){return z[1]}}return null};this.containsKey=function(A){q(A);var z=x(A);var B=i(u,z);return B?B.containsKey(A):false};this.containsValue=function(A){l(A);var z=v.length;while(z--){if(v[z].containsValue(A)){return true}}return false};this.clear=function(){v.length=0;u={}};this.isEmpty=function(){return !v.length};var y=function(z){return function(){var A=[],B=v.length;while(B--){v[B][z](A)}return A}};this.keys=y("keys");this.values=y("values");this.entries=y("getEntries");this.remove=function(B){q(B);var C=x(B),z,A=null;var D=i(u,C);if(D){A=D.removeEntryForKey(B);if(A!==null){if(!D.entries.length){z=m(v,C);n(v,z);delete u[C]}}}return A};this.size=function(){var A=0,z=v.length;while(z--){A+=v[z].entries.length}return A};this.each=function(C){var z=w.entries(),A=z.length,B;while(A--){B=z[A];C(B[0],B[1])}};this.putAll=function(H,C){var B=H.entries();var E,F,D,z,A=B.length;var G=(typeof C==p);while(A--){E=B[A];F=E[0];D=E[1];if(G&&(z=w.get(F))){D=C(F,z,D)}w.put(F,D)}};this.clone=function(){var z=new b(t,r);z.putAll(w);return z}}return b})();(function(b){b.fn.ooLog=function(f,d,e){var c=null;b(this).each(function(){c=b(this).data("_ooLog");if(c==undefined){c=new a();b(this).data("_ooLog",c)}});if(f==undefined){return c}else{if(typeof f==="string"){if(c){c.log(f,d,e)}}}};function a(){return this}a.prototype={isDebugEnabled:function(){return o_info.JSTracingLogDebugEnabled},log:function(e,c,d){if(!this.isDebugEnabled()){return}jQuery.post(o_info.JSTracingUri,{level:e,logMsg:c,jsFile:d})}}})(jQuery);(function(b){b.fn.ooTranslator=function(){var d=null;b(document).each(function(){d=b(document).data("_ooTranslator");if(d==undefined){d=new a();b(document).data("_ooTranslator",d)}});return d};function a(){return this}a.prototype={mapperUrl:null,translators:null,initialize:function(d){this.mapperUrl=d;this.translators=new Object()},getTranslator:function(d,f){if(this.translators[d]==null){this.translators[d]=new Object()}if(this.translators[d][f]==null){var e=this.mapperUrl+"/"+d+"/"+f+"/translations.js";jQuery.ajax(e,{async:false,dataType:"json",success:function(g,i,h){jQuery(document).ooTranslator()._createTranslator(g,d,f)}})}return this.translators[d][f]},_createTranslator:function(e,d,f){this.translators[d][f]=new c().initialize(e,d,f)}};function c(){return this}c.prototype={localizationData:null,bundle:null,locale:null,initialize:function(f,d,e){this.bundle=e;this.locale=d;this.localizationData=f;return this},translate:function(d){if(this.localizationData[d]){return this.localizationData[d]}else{return this.bundle+":"+d}}}})(jQuery);/*! * jQuery periodic plugin * * Copyright 2010, Tom Anderson diff --git a/src/main/webapp/static/js/tinymce/openolat/plugins/olatmovieviewer/olatmovieviewer.htm b/src/main/webapp/static/js/tinymce/openolat/plugins/olatmovieviewer/olatmovieviewer.htm index 72c558105c2..f943ea61a0c 100644 --- a/src/main/webapp/static/js/tinymce/openolat/plugins/olatmovieviewer/olatmovieviewer.htm +++ b/src/main/webapp/static/js/tinymce/openolat/plugins/olatmovieviewer/olatmovieviewer.htm @@ -1,15 +1,16 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> - <script type="text/javascript" src="../../org.olat.core.gui.components.form.flexible.impl.elements.richText/js/tinymce/tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../../../jquery/jquery-1.9.1.min.js"></script> + <script type="text/javascript" src="../../../tinymce/tiny_mce_popup.js"></script> <script type="text/javascript" src="jscripts/helpers.js"></script> <script type="text/javascript" src="jscripts/movieviewer.js"></script> <link type="text/css" rel="stylesheet" href="css/editor.css"></link> - <script type="text/javascript" src="../../../../raw/_noversion_/movie/player.js"></script> - <script type="text/javascript" src="../../org.olat.core.gui.components.form.flexible.impl.elements.richText/js/tinymce/utils/mctabs.js"></script> - <script type="text/javascript" src="../../org.olat.core.gui.components.form.flexible.impl.elements.richText/js/tinymce/utils/validate.js"></script> - <script type="text/javascript" src="../../org.olat.core.gui.components.form.flexible.impl.elements.richText/js/tinymce/utils/form_utils.js"></script> - <script type="text/javascript" src="../../org.olat.core.gui.components.form.flexible.impl.elements.richText/js/tinymce/utils/editable_selects.js"></script> + <script type="text/javascript" src="../../../../../movie/player.js"></script> + <script type="text/javascript" src="../../../tinymce/utils/mctabs.js"></script> + <script type="text/javascript" src="../../../tinymce/utils/validate.js"></script> + <script type="text/javascript" src="../../../tinymce/utils/form_utils.js"></script> + <script type="text/javascript" src="../../../tinymce/utils/editable_selects.js"></script> <script type="text/javascript"> /* <![CDATA[ */ // Load the OLAT translator diff --git a/src/test/java/org/olat/modules/qpool/manager/LOMConverterTest.java b/src/test/java/org/olat/modules/qpool/manager/MetadataConverterHelperTest.java similarity index 68% rename from src/test/java/org/olat/modules/qpool/manager/LOMConverterTest.java rename to src/test/java/org/olat/modules/qpool/manager/MetadataConverterHelperTest.java index 767bee52b65..f465de96b92 100644 --- a/src/test/java/org/olat/modules/qpool/manager/LOMConverterTest.java +++ b/src/test/java/org/olat/modules/qpool/manager/MetadataConverterHelperTest.java @@ -19,17 +19,22 @@ */ package org.olat.modules.qpool.manager; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.URISyntaxException; +import java.util.Locale; import javax.xml.bind.JAXBException; import junit.framework.Assert; import org.junit.Test; +import org.olat.ims.qti.QTIConstants; +import org.olat.modules.qpool.QuestionItem; +import org.olat.modules.qpool.QuestionType; import org.olat.modules.qpool.model.LOMDuration; -import org.olat.modules.qpool.model.QuestionItemImpl; +import org.olat.modules.qpool.model.QItemType; +import org.olat.test.OlatTestCase; +import org.springframework.beans.factory.annotation.Autowired; /** * @@ -37,31 +42,21 @@ import org.olat.modules.qpool.model.QuestionItemImpl; * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ -public class LOMConverterTest { - - @Test - public void itemToLom() - throws IOException, URISyntaxException, JAXBException { - QuestionItemImpl item = new QuestionItemImpl(); - item.setTitle("Psychologie"); - item.setDescription("Description psychologique"); - item.setLanguage("fr"); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - new LOMConverter().toLom(item, out); - out.close(); - System.out.println("LOM: " + new String(out.toByteArray())); - } - +public class MetadataConverterHelperTest extends OlatTestCase { + + @Autowired + private QItemTypeDAO qItemTypeDao; + @Autowired + private QuestionItemDAO questionDao; @Test public void convertDuration_toString() throws IOException, URISyntaxException, JAXBException { //1h 30m - String duration1 = LOMConverter.convertDuration(0, 1, 30, 0); + String duration1 = MetadataConverterHelper.convertDuration(0, 1, 30, 0); Assert.assertEquals("PT1H30M", duration1); //1m 45s - String duration2 = LOMConverter.convertDuration(0, 0, 1, 45); + String duration2 = MetadataConverterHelper.convertDuration(0, 0, 1, 45); Assert.assertEquals("PT1M45S", duration2); } @@ -69,7 +64,7 @@ public class LOMConverterTest { public void convertDuration_toDuration() throws IOException, URISyntaxException, JAXBException { //1h 30m - LOMDuration duration1 = LOMConverter.convertDuration("PT1H30M"); + LOMDuration duration1 = MetadataConverterHelper.convertDuration("PT1H30M"); Assert.assertEquals(0, duration1.getYear()); Assert.assertEquals(0, duration1.getMonth()); Assert.assertEquals(0, duration1.getDay()); @@ -78,7 +73,7 @@ public class LOMConverterTest { Assert.assertEquals(0, duration1.getSeconds()); //1m 45s - LOMDuration duration2 = LOMConverter.convertDuration("PT1M45S"); + LOMDuration duration2 = MetadataConverterHelper.convertDuration("PT1M45S"); Assert.assertEquals(0, duration2.getYear()); Assert.assertEquals(0, duration2.getMonth()); Assert.assertEquals(0, duration2.getDay()); @@ -87,7 +82,7 @@ public class LOMConverterTest { Assert.assertEquals(45, duration2.getSeconds()); //2y 3 month and 4h 1minute 35s - LOMDuration duration3 = LOMConverter.convertDuration("P2Y3MT4H1M35S"); + LOMDuration duration3 = MetadataConverterHelper.convertDuration("P2Y3MT4H1M35S"); Assert.assertEquals(2, duration3.getYear()); Assert.assertEquals(3, duration3.getMonth()); Assert.assertEquals(0, duration3.getDay()); @@ -95,4 +90,14 @@ public class LOMConverterTest { Assert.assertEquals(1, duration3.getMinute()); Assert.assertEquals(35, duration3.getSeconds()); } + + @Test + public void serializeQuestionItem() { + + QItemType fibType = qItemTypeDao.loadByType(QuestionType.FIB.name()); + QuestionItem item = questionDao.createAndPersist(null, "Stars", QTIConstants.QTI_12_FORMAT, Locale.ENGLISH.getLanguage(), null, null, null, fibType); + + + + } } \ No newline at end of file diff --git a/src/test/java/org/olat/test/AllTestsJunit4.java b/src/test/java/org/olat/test/AllTestsJunit4.java index 3c7ccb9b92a..5981106fa30 100644 --- a/src/test/java/org/olat/test/AllTestsJunit4.java +++ b/src/test/java/org/olat/test/AllTestsJunit4.java @@ -122,7 +122,7 @@ import org.junit.runners.Suite; org.olat.ims.qti.qpool.QTIImportProcessorTest.class, org.olat.ims.qti.qpool.QTIExportProcessorTest.class, org.olat.modules.webFeed.FeedManagerImplTest.class, - org.olat.modules.qpool.manager.LOMConverterTest.class, + org.olat.modules.qpool.manager.MetadataConverterHelperTest.class, org.olat.modules.qpool.manager.QuestionDAOTest.class, org.olat.modules.qpool.manager.FileStorageTest.class, org.olat.modules.qpool.manager.CollectionDAOTest.class, -- GitLab