/** * <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.portfolio.ui.structel.edit; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.olat.core.CoreSpringFactory; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.FormItemContainer; import org.olat.core.gui.components.form.flexible.elements.FormLink; import org.olat.core.gui.components.form.flexible.elements.RichTextElement; import org.olat.core.gui.components.form.flexible.elements.SingleSelection; import org.olat.core.gui.components.form.flexible.elements.StaticTextElement; import org.olat.core.gui.components.form.flexible.elements.TextElement; import org.olat.core.gui.components.form.flexible.impl.Form; import org.olat.core.gui.components.form.flexible.impl.FormBasicController; import org.olat.core.gui.components.form.flexible.impl.FormEvent; import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.translator.Translator; import org.olat.core.util.StringHelper; import org.olat.core.util.Util; import org.olat.portfolio.EPArtefactHandler; import org.olat.portfolio.PortfolioModule; import org.olat.portfolio.manager.EPFrontendManager; import org.olat.portfolio.model.restriction.CollectRestriction; import org.olat.portfolio.model.restriction.RestrictionsConstants; import org.olat.portfolio.model.structel.EPStructureElement; import org.olat.portfolio.model.structel.EPStructuredMapTemplate; import org.olat.portfolio.model.structel.PortfolioStructure; import org.olat.portfolio.ui.filter.PortfolioFilterController; import org.olat.portfolio.ui.structel.EPMapViewController; import org.olat.portfolio.ui.structel.EPStructureEvent; /** * Description:<br> * edit the title and details/description of a PortfolioStructure * <P> * Initial Date: 07.10.2010 <br> * * @author Roman Haag, roman.haag@frentix.com, http://www.frentix.com */ public class EPStructureDetailsController extends FormBasicController { private final EPFrontendManager ePFMgr; private final PortfolioModule portfolioModule; private final PortfolioStructure rootStructure; private PortfolioStructure editStructure; public static final String VIEWMODE_TABLE = "table"; public static final String VIEWMODE_MINI = "miniview"; private TextElement titleEl; private RichTextElement descriptionEl; private StaticTextElement noEditInfo; private List<SingleSelection> restrictionElements; private List<SingleSelection> restrictToArtefactElements; private List<TextElement> amountElements; private List<CollectRestriction> collectRestrictions; private SingleSelection viewRadio; private List<StaticTextElement> errorElements; public EPStructureDetailsController(final UserRequest ureq, final WindowControl wControl, final Form rootForm, final PortfolioStructure rootStructure) { super(ureq, wControl, FormBasicController.LAYOUT_DEFAULT, null, rootForm); final Translator pt = Util.createPackageTranslator(EPMapViewController.class, ureq.getLocale(), getTranslator()); flc.setTranslator(pt); ePFMgr = (EPFrontendManager) CoreSpringFactory.getBean("epFrontendManager"); portfolioModule = (PortfolioModule) CoreSpringFactory.getBean("portfolioModule"); this.rootStructure = rootStructure; this.editStructure = rootStructure; // work on a copy of the list in case of cancel collectRestrictions = new ArrayList<CollectRestriction>(editStructure.getCollectRestrictions()); initForm(ureq); } public void setNewStructure(final UserRequest ureq, final PortfolioStructure struct) { editStructure = struct; collectRestrictions = new ArrayList<CollectRestriction>(editStructure.getCollectRestrictions()); updateUI(ureq); } protected void updateUI(final UserRequest ureq) { initForm(ureq); } /** * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#initForm(org.olat.core.gui.components.form.flexible.FormItemContainer, * org.olat.core.gui.control.Controller, org.olat.core.gui.UserRequest) */ @Override protected void initForm(final FormItemContainer formLayout, final Controller listener, final UserRequest ureq) { if (formLayout.getFormComponent("struct.title") != null) { formLayout.remove("struct.title"); } titleEl = uifactory.addTextElement("struct.title", "struct.title", 512, editStructure.getTitle(), formLayout); titleEl.setNotEmptyCheck("map.title.not.empty"); titleEl.setMandatory(true); // choose representation mode (table or minimized artefact-view) if (formLayout.getFormComponent("view.mode") != null) { formLayout.remove("view.mode"); } final String[] theKeys = new String[] { VIEWMODE_TABLE, VIEWMODE_MINI }; final String[] theValues = new String[] { translate("view.mode." + VIEWMODE_TABLE), translate("view.mode." + VIEWMODE_MINI) }; viewRadio = uifactory.addRadiosHorizontal("view.mode", formLayout, theKeys, theValues); final String artRepMode = editStructure.getArtefactRepresentationMode(); if (artRepMode != null) { viewRadio.select(artRepMode, true); } else { viewRadio.select(VIEWMODE_MINI, true); } if (formLayout.getFormComponent("struct.description") != null) { formLayout.remove("struct.description"); } descriptionEl = uifactory.addRichTextElementForStringDataMinimalistic("struct.description", "struct.description", editStructure.getDescription(), -1, -1, formLayout, getWindowControl()); descriptionEl.setMaxLength(2047); descriptionEl.setNotLongerThanCheck(2047, "map.description.too.long"); // hint for no edit options if (formLayout.getFormComponent("noEditInfo") != null) { formLayout.remove("noEditInfo"); } noEditInfo = uifactory.addStaticTextElement("noEditInfo", "no.edit.info.label", translate("no.edit.info"), formLayout); noEditInfo.setVisible(false); if (formLayout.getFormComponent("collect.restriction") != null) { formLayout.remove("collect.restriction"); } // show restrictions only for templates and on page/structure-level, as artefacts are not linkable on maps itself if (editStructure instanceof EPStructureElement && rootStructure instanceof EPStructuredMapTemplate && editStructure.getRoot() != null) { final FormLayoutContainer collectContainer = FormLayoutContainer .createCustomFormLayout("collect.restriction", getTranslator(), velocity_root + "/restrictions.html"); collectContainer.setRootForm(mainForm); collectContainer.setLabel("collect.restriction", null); formLayout.add(collectContainer); final String[] restrictionKeys = new String[] { "", RestrictionsConstants.MAX, RestrictionsConstants.EQUAL, RestrictionsConstants.MIN }; final String[] restrictionValues = new String[restrictionKeys.length]; restrictionValues[0] = ""; for (int i = 1; i < restrictionKeys.length; i++) { restrictionValues[i] = translate("restriction." + restrictionKeys[i]); } final List<EPArtefactHandler<?>> handlers = portfolioModule.getArtefactHandlers(); // allow only to use enabled handlers final String[] artefactKeys = new String[handlers.size() + 1]; final String[] artefactValues = new String[artefactKeys.length]; artefactValues[0] = artefactKeys[0] = ""; for (int i = 0; i < handlers.size(); i++) { final EPArtefactHandler<?> handler = handlers.get(i); artefactKeys[i + 1] = handler.getType(); final String handlerClass = PortfolioFilterController.HANDLER_PREFIX + handler.getClass().getSimpleName() + PortfolioFilterController.HANDLER_TITLE_SUFFIX; artefactValues[i + 1] = handler.getHandlerTranslator(getTranslator()).translate(handlerClass); } if (collectRestrictions.isEmpty()) { collectRestrictions.add(new CollectRestriction()); } restrictionElements = new ArrayList<SingleSelection>(); restrictToArtefactElements = new ArrayList<SingleSelection>(); amountElements = new ArrayList<TextElement>(); errorElements = new ArrayList<StaticTextElement>(); final List<String> counts = new ArrayList<String>(); for (final CollectRestriction restriction : collectRestrictions) { final int count = restrictionElements.size(); final SingleSelection restrictionElement = uifactory.addDropdownSingleselect("collect.restriction.restriction." + count, "", collectContainer, restrictionKeys, restrictionValues, null); restrictionElement.setDomReplacementWrapperRequired(false); restrictionElement.setMandatory(true); if (restriction != null && StringHelper.containsNonWhitespace(restriction.getRestriction())) { restrictionElement.select(restriction.getRestriction(), true); } restrictionElement.setUserObject(restriction); final SingleSelection restrictToArtefactElement = uifactory.addDropdownSingleselect("collect.restriction.artefacts." + count, "", collectContainer, artefactKeys, artefactValues, null); restrictToArtefactElement.setDomReplacementWrapperRequired(false); restrictToArtefactElement.setMandatory(true); if (restriction != null && StringHelper.containsNonWhitespace(restriction.getArtefactType())) { restrictToArtefactElement.select(restriction.getArtefactType(), true); } String amountStr = ""; if (restriction != null && restriction.getAmount() > 0) { amountStr = Integer.toString(restriction.getAmount()); } final TextElement amountElement = uifactory.addTextElement("collect.restriction.amount." + count, null, 2, amountStr, collectContainer); amountElement.setDomReplacementWrapperRequired(false); amountElement.setDisplaySize(3); StaticTextElement errorElement = uifactory.addStaticTextElement("collect.restriction.error." + count, null, "", collectContainer); errorElement.setVisible(false); restrictionElements.add(restrictionElement); restrictToArtefactElements.add(restrictToArtefactElement); amountElements.add(amountElement); errorElements.add(errorElement); final FormLink addLink = uifactory.addFormLink("collect.restriction.add." + count, "collect.restriction.add", "collect.restriction.add", collectContainer, Link.BUTTON_SMALL); addLink.setDomReplacementWrapperRequired(false); addLink.setUserObject(restriction); final FormLink delLink = uifactory.addFormLink("collect.restriction.del." + count, "collect.restriction.delete", "collect.restriction.delete", collectContainer, Link.BUTTON_SMALL); delLink.setDomReplacementWrapperRequired(false); delLink.setUserObject(restriction); counts.add(Integer.toString(count)); } collectContainer.contextPut("counts", counts); } if (formLayout.getFormComponent("save") != null) { formLayout.remove("save"); } uifactory.addFormSubmitButton("save", formLayout); } public FormItem getInitialFormItem() { return flc; } /** * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#validateFormLogic(org.olat.core.gui.UserRequest) */ @Override protected boolean validateFormLogic(UserRequest ureq) { if(rootStructure instanceof EPStructuredMapTemplate && restrictionElements != null) { setCollectRestrictions(); clearErrors(); ArrayList<String> usedTypes = new ArrayList<String>(); int i=0; boolean hasError = false; for(SingleSelection restrictionElement:restrictionElements) { CollectRestriction restriction = (CollectRestriction)restrictionElement.getUserObject(); if (usedTypes.contains(restriction.getArtefactType())){ StaticTextElement thisErrorEl = errorElements.get(i); thisErrorEl.setVisible(true); thisErrorEl.setValue(translate("collect.restriction.duplicate.type")); hasError = true; } usedTypes.add(restriction.getArtefactType()); boolean hasRestriction = StringHelper.containsNonWhitespace(restriction.getRestriction()); boolean hasArtType = StringHelper.containsNonWhitespace(restriction.getArtefactType()); boolean hasAmount = restriction.getAmount() > 0; boolean isValid = restriction.isValid(); if (!isValid && (hasRestriction || hasArtType || hasAmount)) { StaticTextElement thisErrorEl = errorElements.get(i); thisErrorEl.setVisible(true); thisErrorEl.setValue(translate("collect.restriction.incomplete")); hasError = true; } i++; } return !hasError; } return true; } private void clearErrors(){ for (StaticTextElement errorElement : errorElements) { errorElement.setVisible(false); } } /** * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#formOK(org.olat.core.gui.UserRequest) */ @Override protected void formOK(final UserRequest ureq) { editStructure = ePFMgr.reloadPortfolioStructure(editStructure); editStructure.setTitle(titleEl.getValue()); editStructure.setDescription(descriptionEl.getValue()); editStructure.setArtefactRepresentationMode(viewRadio.getSelectedKey()); if (rootStructure instanceof EPStructuredMapTemplate && restrictionElements != null) { clearErrors(); editStructure.getCollectRestrictions().clear(); setCollectRestrictions(); for (final SingleSelection restrictionElement : restrictionElements) { final CollectRestriction restriction = (CollectRestriction) restrictionElement.getUserObject(); if (restriction.isValid()) { final CollectRestriction cr = new CollectRestriction(restriction); editStructure.getCollectRestrictions().add(cr); } } } ePFMgr.savePortfolioStructure(editStructure); fireEvent(ureq, new EPStructureEvent(EPStructureEvent.CHANGE, editStructure)); } @Override protected void formInnerEvent(final UserRequest ureq, final FormItem source, final FormEvent event) { if (source instanceof FormLink && source.getUserObject() instanceof CollectRestriction) { final CollectRestriction restriction = (CollectRestriction) source.getUserObject(); if (source.getName().startsWith("collect.restriction.add.")) { addCollectRestriction(restriction); } else if (source.getName().startsWith("collect.restriction.del.")) { deleteCollectRestriction(restriction); } // secure title and description before redraw UI editStructure.setTitle(titleEl.getValue()); editStructure.setDescription(descriptionEl.getValue()); editStructure.setArtefactRepresentationMode(viewRadio.getSelectedKey()); setCollectRestrictions(); updateUI(ureq); } super.formInnerEvent(ureq, source, event); } protected void setCollectRestrictions() { if (restrictionElements == null || restrictionElements.isEmpty()) { return; } for (int i = 0; i < restrictionElements.size(); i++) { final SingleSelection restrictionElement = restrictionElements.get(i); final SingleSelection restrictToArtefactElement = restrictToArtefactElements.get(i); final TextElement amountElement = amountElements.get(i); final CollectRestriction cr = (CollectRestriction) restrictionElement.getUserObject(); String restriction = ""; if(restrictionElement.isOneSelected()) { restriction = restrictionElement.getSelectedKey(); } String artefactType = ""; if(restrictToArtefactElement.isOneSelected()) { artefactType = restrictToArtefactElement.getSelectedKey(); } final String amount = amountElement.getValue(); cr.setRestriction(restriction); cr.setArtefactType(artefactType); if (StringHelper.containsNonWhitespace(amount)) { try { cr.setAmount(Integer.parseInt(amount)); } catch (final NumberFormatException e) { logWarn("Wrong format for number", e); } } } } protected void addCollectRestriction(final CollectRestriction restriction) { final int index = collectRestrictions.indexOf(restriction); if (index + 1 < collectRestrictions.size()) { collectRestrictions.add(index + 1, new CollectRestriction()); } else { collectRestrictions.add(new CollectRestriction()); } } protected void deleteCollectRestriction(final CollectRestriction restriction) { collectRestrictions.remove(restriction); } /** * @see org.olat.core.gui.control.DefaultController#doDispose() */ @Override protected void doDispose() { // nothing to dispose } // disable all formitems expect a hint, when nothing was selected or an artefact was selected public void setNoStructure() { editStructure = null; final Map<String, FormItem> comps = flc.getFormComponents(); for (final Iterator<Entry<String, FormItem>> iterator = comps.entrySet().iterator(); iterator.hasNext();) { final Entry<String, FormItem> entry = iterator.next(); entry.getValue().setVisible(false); } noEditInfo.setVisible(true); flc.setDirty(true); } }