/** * <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.repository.ui.catalog; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; import org.olat.NewControllerFactory; import org.olat.admin.securitygroup.gui.GroupController; import org.olat.admin.securitygroup.gui.IdentitiesAddEvent; import org.olat.admin.securitygroup.gui.IdentitiesRemoveEvent; import org.olat.basesecurity.BaseSecurity; import org.olat.basesecurity.SecurityGroup; import org.olat.core.dispatcher.mapper.MapperService; import org.olat.core.dispatcher.mapper.manager.MapperKey; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; 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.FlexiTableElement; 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.elements.table.DateFlexiCellRenderer; import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiCellRenderer; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer; import org.olat.core.gui.components.form.flexible.impl.elements.table.TextFlexiCellRenderer; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.link.LinkFactory; import org.olat.core.gui.components.stack.TooledStackedPanel; import org.olat.core.gui.components.stack.TooledStackedPanel.Align; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController; import org.olat.core.gui.control.generic.dtabs.Activateable2; import org.olat.core.gui.control.generic.modal.DialogBoxController; import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory; import org.olat.core.helpers.Settings; import org.olat.core.id.Identity; import org.olat.core.id.OLATResourceable; import org.olat.core.id.context.BusinessControlFactory; import org.olat.core.id.context.ContextEntry; import org.olat.core.id.context.StateEntry; import org.olat.core.logging.activity.ThreadLocalUserActivityLogger; import org.olat.core.util.StringHelper; import org.olat.core.util.Util; import org.olat.core.util.coordinate.CoordinatorManager; import org.olat.core.util.coordinate.LockResult; import org.olat.core.util.mail.ContactList; import org.olat.core.util.mail.ContactMessage; import org.olat.core.util.resource.OresHelper; import org.olat.core.util.vfs.VFSLeaf; import org.olat.login.LoginModule; import org.olat.modules.co.ContactFormController; import org.olat.repository.CatalogEntry; import org.olat.repository.CatalogEntry.Style; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryEntryRef; import org.olat.repository.RepositoryManager; import org.olat.repository.RepositoryModule; import org.olat.repository.RepositoryService; import org.olat.repository.controllers.RepositorySearchController; import org.olat.repository.manager.CatalogManager; import org.olat.repository.model.SearchAuthorRepositoryEntryViewParams.OrderBy; import org.olat.repository.model.SearchRepositoryEntryParameters; import org.olat.repository.ui.CatalogEntryImageMapper; import org.olat.repository.ui.PriceMethod; import org.olat.repository.ui.RepositoryTableModel; import org.olat.repository.ui.author.ACRenderer; import org.olat.repository.ui.author.AccessRenderer; import org.olat.repository.ui.author.TypeRenderer; import org.olat.repository.ui.catalog.CatalogEntryRowModel.Cols; import org.olat.resource.OLATResource; import org.olat.resource.accesscontrol.ACService; import org.olat.resource.accesscontrol.AccessControlModule; import org.olat.resource.accesscontrol.method.AccessMethodHandler; import org.olat.resource.accesscontrol.model.OLATResourceAccess; import org.olat.resource.accesscontrol.model.PriceMethodBundle; import org.olat.resource.accesscontrol.ui.PriceFormat; import org.olat.user.UserManager; import org.olat.util.logging.activity.LoggingResourceable; import org.springframework.beans.factory.annotation.Autowired; /** * * Initial date: 04.12.2014<br> * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ public class CatalogNodeManagerController extends FormBasicController implements Activateable2 { public static final String LOCK_TOKEN = "catalogeditlock"; public static final OLATResourceable lockRes = OresHelper.createOLATResourceableType("CatalogNodeManagerController"); private final TooledStackedPanel toolbarPanel; private GroupController groupCtrl; private CloseableModalController cmc; private ContactFormController contactCtrl; private RepositorySearchController entrySearchCtrl; private CatalogNodeManagerController childNodeCtrl; private CatalogEntryMoveController categoryMoveCtrl; private CatalogEntryMoveController entryResourceMoveCtrl; private CatalogEntryEditController addEntryCtrl, editEntryCtrl; private DialogBoxController dialogDeleteLink, dialogDeleteSubtree; private FlexiTableElement entriesEl, closedEntriesEl; private CatalogEntryRowModel entriesModel, closedEntriesModel; private Link editLink, moveLink, deleteLink; private Link nominateLink, contactLink; private Link addCategoryLink, addResourceLink; private LockResult catModificationLock; private final MapperKey mapperThumbnailKey; private final WindowControl rootwControl; private final boolean isGuest; private final boolean isAuthor; private final boolean isOLATAdmin; private final boolean isLocalTreeAdmin; private CatalogEntry catalogEntry; @Autowired private ACService acService; @Autowired private UserManager userManager; @Autowired private LoginModule loginModule; @Autowired private AccessControlModule acModule; @Autowired private RepositoryModule repositoryModule; @Autowired private MapperService mapperService; @Autowired private CatalogManager catalogManager; @Autowired private BaseSecurity securityManager; @Autowired private RepositoryManager repositoryManager; public CatalogNodeManagerController(UserRequest ureq, WindowControl wControl, WindowControl rootwControl, CatalogEntry catalogEntry, TooledStackedPanel stackPanel, boolean localTreeAdmin) { super(ureq, wControl, "node"); setTranslator(Util.createPackageTranslator(RepositoryService.class, ureq.getLocale(), getTranslator())); this.toolbarPanel = stackPanel; this.catalogEntry = catalogEntry; this.rootwControl = rootwControl; mapperThumbnailKey = mapperService.register(null, "catalogentryImage", new CatalogEntryImageMapper()); isAuthor = ureq.getUserSession().getRoles().isAuthor(); isGuest = ureq.getUserSession().getRoles().isGuestOnly(); isOLATAdmin = ureq.getUserSession().getRoles().isOLATAdmin(); if(isOLATAdmin) { isLocalTreeAdmin = false; } else { isLocalTreeAdmin = localTreeAdmin || securityManager .isIdentityInSecurityGroup(ureq.getIdentity(), catalogEntry.getOwnerGroup()); } initForm(ureq); loadEntryInfos(); loadNodesChildren(); loadResources(ureq); //catch the events from the velocity template flc.getFormItemComponent().addListener(this); } @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { //one mapper for all users flc.contextPut("mapperThumbnailUrl", mapperThumbnailKey.getUrl()); int level = 0; CatalogEntry parent = catalogEntry.getParent(); while (parent != null) { level++; parent = parent.getParent(); } flc.contextPut("catalogLevel", level); String url = Settings.getServerContextPathURI() + "/url/CatalogEntry/" + catalogEntry.getKey(); if(loginModule.isGuestLoginLinksEnabled()) { flc.contextPut("guestExtLink", url + "?guest=true&lang=" + getLocale().getLanguage()); } if (!isGuest) { flc.contextPut("extLink", url); } FlexiTableColumnModel entriesColumnsModel = getCatalogFlexiTableColumnModel("opened-"); entriesModel = new CatalogEntryRowModel(entriesColumnsModel); entriesEl = uifactory.addTableElement(getWindowControl(), "entries", entriesModel, getTranslator(), formLayout); FlexiTableColumnModel closedEntriesColumnsModel = getCatalogFlexiTableColumnModel("closed-"); closedEntriesModel = new CatalogEntryRowModel(closedEntriesColumnsModel); closedEntriesEl = uifactory.addTableElement(getWindowControl(), "closedEntries", closedEntriesModel, getTranslator(), formLayout); } private FlexiTableColumnModel getCatalogFlexiTableColumnModel(String cmdPrefix) { //add the table FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.key.i18nKey(), Cols.key.ordinal(), true, OrderBy.key.name())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, Cols.type.i18nKey(), Cols.type.ordinal(), true, OrderBy.type.name(), FlexiColumnModel.ALIGNMENT_LEFT, new TypeRenderer())); FlexiCellRenderer renderer = new StaticFlexiCellRenderer(cmdPrefix + "select", new TextFlexiCellRenderer()); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.displayName.i18nKey(), Cols.displayName.ordinal(), cmdPrefix + "select", true, OrderBy.displayname.name(), renderer)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.authors.i18nKey(), Cols.authors.ordinal(), true, OrderBy.authors.name())); if(repositoryModule.isManagedRepositoryEntries()) { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.externalId.i18nKey(), Cols.externalId.ordinal(), true, OrderBy.externalId.name())); } columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.externalRef.i18nKey(), Cols.externalRef.ordinal(), true, OrderBy.externalRef.name())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.lifecycleLabel.i18nKey(), Cols.lifecycleLabel.ordinal(), true, OrderBy.lifecycleLabel.name())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.lifecycleSoftkey.i18nKey(), Cols.lifecycleSoftkey.ordinal(), true, OrderBy.lifecycleSoftkey.name())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, Cols.lifecycleStart.i18nKey(), Cols.lifecycleStart.ordinal(), true, OrderBy.lifecycleStart.name(), FlexiColumnModel.ALIGNMENT_LEFT, new DateFlexiCellRenderer(getLocale()))); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, Cols.lifecycleEnd.i18nKey(), Cols.lifecycleEnd.ordinal(), true, OrderBy.lifecycleEnd.name(), FlexiColumnModel.ALIGNMENT_LEFT, new DateFlexiCellRenderer(getLocale()))); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, Cols.access.i18nKey(), Cols.access.ordinal(), true, OrderBy.access.name(), FlexiColumnModel.ALIGNMENT_LEFT, new AccessRenderer())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, Cols.ac.i18nKey(), Cols.ac.ordinal(), true, OrderBy.ac.name(), FlexiColumnModel.ALIGNMENT_LEFT, new ACRenderer())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.creationDate.i18nKey(), Cols.creationDate.ordinal(), true, OrderBy.creationDate.name())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.delete.i18nKey(), translate(Cols.delete.i18nKey()), cmdPrefix + "delete")); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.move.i18nKey(), translate(Cols.move.i18nKey()), cmdPrefix + "move")); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.detailsSupported.i18nKey(), Cols.detailsSupported.ordinal(), cmdPrefix + "details", new StaticFlexiCellRenderer("", cmdPrefix + "details", "o_icon o_icon-lg o_icon_details", translate("details")))); return columnsModel; } private void loadEntryInfos() { flc.contextPut("catalogEntryName", catalogEntry.getName()); if(StringHelper.containsNonWhitespace(catalogEntry.getDescription())) { flc.contextPut("catalogEntryDesc", catalogEntry.getDescription()); } VFSLeaf image = catalogManager.getImage(catalogEntry); if(image != null) { flc.contextPut("catThumbnail", image.getName()); } if(catalogEntry.getStyle() != null) { flc.contextPut("listStyle", catalogEntry.getStyle().name()); } else { flc.contextPut("listStyle", Style.tiles.name()); } } private void loadResources(UserRequest ureq) { SearchRepositoryEntryParameters params = new SearchRepositoryEntryParameters(getIdentity(), ureq.getUserSession().getRoles()); params.setParentEntry(catalogEntry); List<RepositoryEntry> repoEntries = repositoryManager.genericANDQueryWithRolesRestriction(params, 0, -1, false); List<Long> resourceKeys = new ArrayList<>(); for (RepositoryEntry entry : repoEntries) { resourceKeys.add(entry.getOlatResource().getKey()); } List<OLATResourceAccess> resourcesWithOffer = acService.getAccessMethodForResources(resourceKeys, null, true, new Date()); List<CatalogEntryRow> items = new ArrayList<>(); List<CatalogEntryRow> closedItems = new ArrayList<>(); for(RepositoryEntry entry:repoEntries) { CatalogEntryRow row = new CatalogEntryRow(entry); List<PriceMethod> types = new ArrayList<PriceMethod>(); if (entry.isMembersOnly()) { // members only always show lock icon types.add(new PriceMethod("", "o_ac_membersonly_icon", translate("cif.access.membersonly.short"))); } else { // collect access control method icons OLATResource resource = entry.getOlatResource(); for(OLATResourceAccess resourceAccess:resourcesWithOffer) { if(resource.getKey().equals(resourceAccess.getResource().getKey())) { for(PriceMethodBundle bundle:resourceAccess.getMethods()) { String type = (bundle.getMethod().getMethodCssClass() + "_icon").intern(); String price = bundle.getPrice() == null || bundle.getPrice().isEmpty() ? "" : PriceFormat.fullFormat(bundle.getPrice()); AccessMethodHandler amh = acModule.getAccessMethodHandler(bundle.getMethod().getType()); String displayName = amh.getMethodName(getLocale()); types.add(new PriceMethod(price, type, displayName)); } } } } if(!types.isEmpty()) { row.setAccessTypes(types); } if(entry.getRepositoryEntryStatus().isClosed()) { closedItems.add(row); } else { items.add(row); } } entriesModel.setObjects(items); entriesEl.reset(); entriesEl.setVisible(entriesModel.getRowCount() > 0); closedEntriesModel.setObjects(closedItems); closedEntriesEl.reset(); closedEntriesEl.setVisible(closedEntriesModel.getRowCount() > 0); } protected void loadNodesChildren() { List<CatalogEntry> childCe = catalogManager.getNodesChildrenOf(catalogEntry); Collections.sort(childCe, new CatalogEntryComparator(getLocale())); List<String> subCategories = new ArrayList<>(); int count = 0; for (CatalogEntry entry : childCe) { if(entry.getType() == CatalogEntry.TYPE_NODE) { String cmpId = "cat_" + (++count); VFSLeaf img = catalogManager.getImage(entry); if(img != null) { String imgId = "image_" + count; flc.contextPut(imgId, img.getName()); } flc.contextPut("k" + cmpId, entry.getKey()); String title = StringHelper.escapeHtml(entry.getName()); Link link = LinkFactory.createCustomLink(cmpId, "select_node", cmpId, Link.LINK + Link.NONTRANSLATED, flc.getFormItemComponent(), this); link.setIconLeftCSS("o_icon o_icon_catalog_sub"); link.setCustomDisplayText(title); link.setUserObject(entry.getKey()); subCategories.add(Integer.toString(count)); String titleId = "title_" + count; flc.contextPut(titleId, title); } } flc.contextPut("subCategories", subCategories); } protected void initToolbar() { boolean canAddLinks = isOLATAdmin || isAuthor; // author is allowed to add! boolean canAdministrateCategory = isOLATAdmin || isLocalTreeAdmin; boolean canAddSubCategories = isOLATAdmin || isLocalTreeAdmin; if (canAdministrateCategory || canAddLinks) { if (canAdministrateCategory) { editLink = LinkFactory.createToolLink("edit", translate("tools.edit.catalog.category"), this, "o_icon_edit"); editLink.setElementCssClass("o_sel_catalog_edit_category"); toolbarPanel.addTool(editLink, Align.left); } if (canAdministrateCategory) { nominateLink = LinkFactory.createToolLink("nominate", translate("tools.edit.catalog.category.ownergroup"), this, "o_icon_user"); nominateLink.setElementCssClass("o_sel_catalog_category_owner"); toolbarPanel.addTool(nominateLink, Align.right); } if (canAddLinks) { contactLink = LinkFactory.createToolLink("contact", translate("tools.new.catalog.categoryrequest"), this, "o_icon_mail"); contactLink.setElementCssClass("o_sel_catalog_contact_owner"); toolbarPanel.addTool(contactLink, Align.right); } if (canAdministrateCategory && catalogEntry.getParent() != null) { // delete root? very dangerous, disabled! deleteLink = LinkFactory.createToolLink("delete", translate("tools.delete.catalog.entry"), this, "o_icon_delete"); deleteLink.setElementCssClass("o_sel_catalog_delete_category"); toolbarPanel.addTool(deleteLink, Align.left); } if (canAdministrateCategory && catalogEntry.getParent() != null) { moveLink = LinkFactory.createToolLink("move", translate("tools.move.catalog.entry"), this, "o_icon_move"); moveLink.setElementCssClass("o_sel_catalog_move_category"); toolbarPanel.addTool(moveLink, Align.left); } } if(isOLATAdmin || isLocalTreeAdmin || isAuthor) { if (canAddSubCategories) { addCategoryLink = LinkFactory.createToolLink("addResource", translate("tools.add.catalog.category"), this, "o_icon_catalog_sub"); addCategoryLink.setElementCssClass("o_sel_catalog_add_category"); toolbarPanel.addTool(addCategoryLink, Align.left); } if (canAddLinks) { addResourceLink = LinkFactory.createToolLink("addResource", translate("tools.add.catalog.link"), this, "o_icon_add"); addResourceLink.setElementCssClass("o_sel_catalog_add_link_to_resource"); toolbarPanel.addTool(addResourceLink, Align.left); } } } @Override protected void doDispose() { // } @Override public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) { if(entries == null || entries.isEmpty()) { return; } ContextEntry entry = entries.get(0); String type = entry.getOLATResourceable().getResourceableTypeName(); if("CatalogEntry".equalsIgnoreCase(type)) { Long entryKey = entry.getOLATResourceable().getResourceableId(); if(entryKey != null && entryKey.longValue() > 0) { activateRoot(ureq, entryKey); } } else if("Node".equalsIgnoreCase(type)) { //the "Node" is only for internal usage StateEntry stateEntry = entry.getTransientState(); if(stateEntry instanceof CatalogStateEntry) { CatalogEntry catEntry = ((CatalogStateEntry)stateEntry).getEntry(); CatalogNodeManagerController nextCtrl = selectCatalogEntry(ureq, catEntry); if(nextCtrl != null && entries.size() > 1) { nextCtrl.activate(ureq, entries.subList(1, entries.size()), null); } } } } /** * Build an internal business path made of "Node" with the category * as state entry to prevent loading several times the same entries. * * @param ureq * @param entryKey */ private void activateRoot(UserRequest ureq, Long entryKey) { List<ContextEntry> parentLine = new ArrayList<>(); for(CatalogEntry node = catalogManager.getCatalogEntryByKey(entryKey); node.getParent() != null; node=node.getParent()) { OLATResourceable nodeRes = OresHelper.createOLATResourceableInstance("Node", node.getKey()); ContextEntry ctxEntry = BusinessControlFactory.getInstance().createContextEntry(nodeRes); ctxEntry.setTransientState(new CatalogStateEntry(node)); parentLine.add(ctxEntry); } Collections.reverse(parentLine); activate(ureq, parentLine, null); } @Override protected void formOK(UserRequest ureq) { // } @Override protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { if(entriesEl == source) { if(event instanceof SelectionEvent) { SelectionEvent se = (SelectionEvent)event; String cmd = se.getCommand(); if(cmd != null && cmd.startsWith("opened-")) { CatalogEntryRow row = entriesModel.getObject(se.getIndex()); if("opened-details".equals(cmd) || "opened-select".equals(cmd)) { launchDetails(ureq, row); } else if("opened-move".equals(cmd)) { doMoveCategory(ureq, row); } else if("opened-delete".equals(cmd)) { doConfirmDelete(ureq, row); } } } } else if(closedEntriesEl == source) { if(event instanceof SelectionEvent) { SelectionEvent se = (SelectionEvent)event; String cmd = se.getCommand(); if(cmd != null && cmd.startsWith("closed-")) { CatalogEntryRow row = closedEntriesModel.getObject(se.getIndex()); if("closed-details".equals(cmd) || "closed-select".equals(cmd)) { launchDetails(ureq, row); } else if("closed-move".equals(cmd)) { doMoveCategory(ureq, row); } else if("closed-delete".equals(cmd)) { doConfirmDelete(ureq, row); } } } } super.formInnerEvent(ureq, source, event); } @Override public void event(UserRequest ureq, Component source, Event event) { if(editLink == source){ doEditCategory(ureq); } else if(nominateLink == source) { doEditOwners(ureq); } else if(contactLink == source) { doContact(ureq); } else if(deleteLink == source) { doConfirmDelete(ureq); } else if(moveLink == source) { doMoveCategory(ureq); } else if(addCategoryLink == source) { doAddCategory(ureq); } else if(addResourceLink == source) { doAddResource(ureq); } else if(source instanceof Link) { Link link = (Link)source; if("select_node".equals(link.getCommand())) { Long categoryNodeKey = (Long)link.getUserObject(); CatalogEntry entry = catalogManager.getCatalogNodeByKey(categoryNodeKey); selectCatalogEntry(ureq, entry); } } else if("img_select".equals(event.getCommand())) { String node = ureq.getParameter("node"); if(StringHelper.isLong(node)) { try { Long categoryNodeKey = new Long(node); CatalogEntry entry = catalogManager.getCatalogNodeByKey(categoryNodeKey); selectCatalogEntry(ureq, entry); } catch (NumberFormatException e) { logWarn("Not a valid long: " + node, e); } } } super.event(ureq, source, event); } @Override protected void event(UserRequest ureq, Controller source, Event event) { if(addEntryCtrl == source) { if(event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) { loadNodesChildren(); } cmc.deactivate(); cleanUp(); fireEvent(ureq, Event.CHANGED_EVENT); } else if(editEntryCtrl == source) { if(event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) { catalogEntry = editEntryCtrl.getEditedCatalogEntry(); loadEntryInfos(); } cmc.deactivate(); cleanUp(); fireEvent(ureq, Event.CHANGED_EVENT); } else if(categoryMoveCtrl == source) { cmc.deactivate(); CatalogEntry moveMe = null; if(event.equals(Event.DONE_EVENT)){ showInfo("tools.move.catalog.entry.success", catalogEntry.getName()); moveMe = categoryMoveCtrl.getMoveMe(); } else if(event.equals(Event.FAILED_EVENT)){ showError("tools.move.catalog.entry.failed"); loadNodesChildren(); } cleanUp(); // in any case, remove the lock if (catModificationLock != null && catModificationLock.isSuccess()) { CoordinatorManager.getInstance().getCoordinator().getLocker().releaseLock(catModificationLock); catModificationLock = null; } //only after jump to the moved entry if(moveMe != null) { launchCatalogEntry(ureq, moveMe); } } else if(dialogDeleteSubtree == source) { //from remove subtree dialog -> yes or no if (DialogBoxUIFactory.isYesEvent(event)) { catalogManager.deleteCatalogEntry(catalogEntry); fireEvent(ureq, Event.BACK_EVENT); } // in any case, remove the lock if (catModificationLock != null && catModificationLock.isSuccess()) { CoordinatorManager.getInstance().getCoordinator().getLocker().releaseLock(catModificationLock); catModificationLock = null; } } else if(childNodeCtrl == source) { if(event == Event.BACK_EVENT) { toolbarPanel.popUpToController(this); removeAsListenerAndDispose(childNodeCtrl); childNodeCtrl = null; loadNodesChildren(); } } else if(entrySearchCtrl == source) { if (event.getCommand().equals(RepositoryTableModel.TABLE_ACTION_SELECT_LINK)) { // successfully selected a repository entry which will be a link within // the current Category RepositoryEntry selectedEntry = entrySearchCtrl.getSelectedEntry(); doAddResource(ureq, selectedEntry); fireEvent(ureq, Event.CHANGED_EVENT); } cmc.deactivate(); cleanUp(); } else if(groupCtrl == source) { if(event instanceof IdentitiesAddEvent || event instanceof IdentitiesRemoveEvent) { doAddRemoveOwners(event); } } else if(contactCtrl == source) { cmc.deactivate(); cleanUp(); } else if(dialogDeleteLink == source) { if (DialogBoxUIFactory.isYesEvent(event)) { CatalogEntryRow row = (CatalogEntryRow)dialogDeleteLink.getUserObject(); catalogManager.deleteCatalogEntry(row, catalogEntry); loadResources(ureq); } } else if(entryResourceMoveCtrl == source) { if(event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) { CatalogEntry moveMe = entryResourceMoveCtrl.getMoveMe(); showInfo("tools.move.catalog.entry.success", moveMe.getName()); loadResources(ureq); } cmc.deactivate(); cleanUp(); } else if(cmc == source) { cleanUp(); } super.event(ureq, source, event); } private void cleanUp() { //remove the lock, always if (catModificationLock != null && catModificationLock.isSuccess()) { CoordinatorManager.getInstance().getCoordinator().getLocker().releaseLock(catModificationLock); catModificationLock = null; } removeAsListenerAndDispose(cmc); removeAsListenerAndDispose(groupCtrl); removeAsListenerAndDispose(contactCtrl); removeAsListenerAndDispose(addEntryCtrl); removeAsListenerAndDispose(editEntryCtrl); removeAsListenerAndDispose(entrySearchCtrl); cmc = null; groupCtrl = null; contactCtrl = null; addEntryCtrl = null; editEntryCtrl = null; entrySearchCtrl = null; } private CatalogNodeManagerController selectCatalogEntry(UserRequest ureq, CatalogEntry entry) { if(entry != null && entry.getType() == CatalogEntry.TYPE_NODE) { removeAsListenerAndDispose(childNodeCtrl); OLATResourceable ores = OresHelper.createOLATResourceableInstance("CatalogEntry", entry.getKey()); ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrapBusinessPath(ores)); WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, rootwControl); childNodeCtrl = new CatalogNodeManagerController(ureq, bwControl, rootwControl, entry, toolbarPanel, isLocalTreeAdmin); listenTo(childNodeCtrl); toolbarPanel.pushController(entry.getName(), childNodeCtrl); childNodeCtrl.initToolbar(); addToHistory(ureq, childNodeCtrl); } return childNodeCtrl; } private void doAddResource(UserRequest ureq) { removeAsListenerAndDispose(entrySearchCtrl); removeAsListenerAndDispose(cmc); entrySearchCtrl = new RepositorySearchController(translate("choose"), ureq, getWindowControl(), true, false, new String[0], null); listenTo(entrySearchCtrl); // OLAT-Admin has search form if (ureq.getUserSession().getRoles().isOLATAdmin()) { entrySearchCtrl.displaySearchForm(); } // an Author gets the list of his repository else { // admin is responsible for not inserting wrong visibility entries!! entrySearchCtrl.doSearchByOwnerLimitAccess(ureq.getIdentity()); } // open form in dialog cmc = new CloseableModalController(getWindowControl(), "close", entrySearchCtrl.getInitialComponent(), true, translate("tools.add.catalog.link")); listenTo(cmc); cmc.activate(); } private void doAddResource(UserRequest ureq, RepositoryEntry selectedEntry) { CatalogEntry newLinkNotPersistedYet = catalogManager.createCatalogEntry(); newLinkNotPersistedYet.setName(selectedEntry.getDisplayname()); newLinkNotPersistedYet.setDescription(selectedEntry.getDescription()); newLinkNotPersistedYet.setRepositoryEntry(selectedEntry); newLinkNotPersistedYet.setType(CatalogEntry.TYPE_LEAF); newLinkNotPersistedYet.setOwnerGroup(securityManager.createAndPersistSecurityGroup()); catalogManager.addCatalogEntry(catalogEntry, newLinkNotPersistedYet); loadResources(ureq); } private void doAddCategory(UserRequest ureq) { removeAsListenerAndDispose(addEntryCtrl); removeAsListenerAndDispose(cmc); catModificationLock = CoordinatorManager.getInstance().getCoordinator().getLocker().acquireLock(lockRes, getIdentity(), LOCK_TOKEN); if (catModificationLock.isSuccess()) { CatalogEntry ce = catalogManager.createCatalogEntry(); addEntryCtrl = new CatalogEntryEditController(ureq, getWindowControl(), ce, catalogEntry); addEntryCtrl.setElementCssClass("o_sel_catalog_add_category_popup"); listenTo(addEntryCtrl); cmc = new CloseableModalController(getWindowControl(), "close", addEntryCtrl.getInitialComponent(), true, translate("tools.add.catalog.category")); listenTo(cmc); cmc.activate(); } else { String ownerName = userManager.getUserDisplayName(catModificationLock.getOwner()); showError("catalog.locked.by", ownerName); } } private void doEditCategory(UserRequest ureq) { removeAsListenerAndDispose(editEntryCtrl); removeAsListenerAndDispose(cmc); catModificationLock = CoordinatorManager.getInstance().getCoordinator().getLocker().acquireLock(lockRes, getIdentity(), LOCK_TOKEN); if ( catModificationLock.isSuccess()) { editEntryCtrl = new CatalogEntryEditController(ureq, getWindowControl(), catalogEntry); editEntryCtrl.setElementCssClass("o_sel_catalog_edit_category_popup"); listenTo(editEntryCtrl); // open form in dialog cmc = new CloseableModalController(getWindowControl(), "close", editEntryCtrl.getInitialComponent(), true, translate("tools.edit.catalog.category")); listenTo(cmc); cmc.activate(); } else { String ownerName = userManager.getUserDisplayName(catModificationLock.getOwner()); showError("catalog.locked.by", ownerName); } } private void doMoveCategory(UserRequest ureq) { removeAsListenerAndDispose(cmc); removeAsListenerAndDispose(categoryMoveCtrl); catModificationLock = CoordinatorManager.getInstance().getCoordinator().getLocker().acquireLock(lockRes, getIdentity(), LOCK_TOKEN); if (catModificationLock.isSuccess()) { categoryMoveCtrl= new CatalogEntryMoveController(getWindowControl(), ureq, catalogEntry, getTranslator()); listenTo(categoryMoveCtrl); cmc = new CloseableModalController(getWindowControl(), "close", categoryMoveCtrl.getInitialComponent(), true, translate("tools.move.catalog.entry")); listenTo(cmc); cmc.activate(); } else { String ownerName = userManager.getUserDisplayName(catModificationLock.getOwner()); showError("catalog.locked.by", ownerName); } } private void doMoveCategory(UserRequest ureq, CatalogEntryRow row) { removeAsListenerAndDispose(cmc); removeAsListenerAndDispose(entryResourceMoveCtrl); CatalogEntry moveMe = catalogManager.getCatalogEntryBy(row, catalogEntry); if(moveMe != null) { entryResourceMoveCtrl= new CatalogEntryMoveController(getWindowControl(), ureq, moveMe, getTranslator()); listenTo(entryResourceMoveCtrl); cmc = new CloseableModalController(getWindowControl(), "close", entryResourceMoveCtrl.getInitialComponent(), true, translate("tools.move.catalog.entry")); listenTo(cmc); cmc.activate(); } } private void doConfirmDelete(UserRequest ureq) { catModificationLock = CoordinatorManager.getInstance().getCoordinator().getLocker().acquireLock(lockRes, getIdentity(), LOCK_TOKEN); if ( catModificationLock.isSuccess()) { String[] trnslP = { catalogEntry.getName() }; dialogDeleteSubtree = activateYesNoDialog(ureq, null, translate("dialog.modal.subtree.delete.text", trnslP), dialogDeleteSubtree); } else { String ownerName = userManager.getUserDisplayName(catModificationLock.getOwner()); showError("catalog.locked.by", ownerName); } } private void doConfirmDelete(UserRequest ureq, CatalogEntryRow row) { String[] trnslP = { row.getDisplayname() }; dialogDeleteLink = activateYesNoDialog(ureq, null, translate("dialog.modal.leaf.delete.text", trnslP), dialogDeleteLink); dialogDeleteLink.setUserObject(row); } private void doEditOwners(UserRequest ureq) { removeAsListenerAndDispose(groupCtrl); removeAsListenerAndDispose(cmc); // add ownership management SecurityGroup secGroup = catalogEntry.getOwnerGroup(); if (secGroup == null) { catalogEntry = catalogManager.loadCatalogEntry(catalogEntry); secGroup = securityManager.createAndPersistSecurityGroup(); catalogEntry.setOwnerGroup(secGroup); catalogEntry = catalogManager.saveCatalogEntry(catalogEntry); } groupCtrl = new GroupController(ureq, getWindowControl(), true, false, false, false, false, false, secGroup); listenTo(groupCtrl); // open form in dialog removeAsListenerAndDispose(cmc); cmc = new CloseableModalController(getWindowControl(), "close", groupCtrl.getInitialComponent(), true, translate("tools.edit.catalog.category.ownergroup")); listenTo(cmc); cmc.activate(); } private void doAddRemoveOwners(Event event) { if(event instanceof IdentitiesAddEvent ) { IdentitiesAddEvent identitiesAddedEvent = (IdentitiesAddEvent) event; List<Identity> list = identitiesAddedEvent.getAddIdentities(); for (Identity identity : list) { if (!securityManager.isIdentityInSecurityGroup(identity, catalogEntry.getOwnerGroup())) { securityManager.addIdentityToSecurityGroup(identity, catalogEntry.getOwnerGroup()); identitiesAddedEvent.getAddedIdentities().add(identity); } } } else if (event instanceof IdentitiesRemoveEvent) { IdentitiesRemoveEvent identitiesRemoveEvent = (IdentitiesRemoveEvent) event; List<Identity> list = identitiesRemoveEvent.getRemovedIdentities(); for (Identity identity : list) { securityManager.removeIdentityFromSecurityGroup(identity, catalogEntry.getOwnerGroup()); } } } private void doContact(UserRequest ureq) { removeAsListenerAndDispose(cmc); removeAsListenerAndDispose(contactCtrl); ContactList caretaker = new ContactList(translate("contact.to.groupname.caretaker")); List<Identity> owners = new ArrayList<Identity>(); CatalogEntry parent = catalogEntry; while(parent != null && owners.isEmpty()) { SecurityGroup parentOwner = parent.getOwnerGroup(); if (parentOwner != null) { owners = securityManager.getIdentitiesOfSecurityGroup(parentOwner); } parent = parent.getParent(); } for (int i=owners.size(); i-->0; ) { caretaker.add(owners.get(i)); } //create e-mail Message ContactMessage cmsg = new ContactMessage(ureq.getIdentity()); cmsg.addEmailTo(caretaker); contactCtrl = new ContactFormController(ureq, getWindowControl(), true, false, false, cmsg); listenTo(contactCtrl); // open form in dialog cmc = new CloseableModalController(getWindowControl(), "close", contactCtrl.getInitialComponent(), true, translate("contact.caretaker")); listenTo(cmc); cmc.activate(); } private void launchDetails(UserRequest ureq, RepositoryEntryRef ref) { String businessPath = "[RepositoryEntry:" + ref.getKey() + "][Infos:0]"; NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl()); } private void launchCatalogEntry(UserRequest ureq, CatalogEntry ref) { String businessPath = "[CatalogAdmin:0][CatalogEntry:" + ref.getKey() + "]"; NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl()); } }