/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <hr>
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* This file has been modified by the OpenOLAT community. Changes are licensed
* under the Apache 2.0 license as the original file.
*/
package org.olat.group.ui.portlet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.olat.NewControllerFactory;
import org.olat.core.CoreSpringFactory;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.link.Link;
import org.olat.core.gui.components.link.LinkFactory;
import org.olat.core.gui.components.table.DefaultColumnDescriptor;
import org.olat.core.gui.components.table.Table;
import org.olat.core.gui.components.table.TableController;
import org.olat.core.gui.components.table.TableEvent;
import org.olat.core.gui.components.table.TableGuiConfiguration;
import org.olat.core.gui.components.velocity.VelocityContainer;
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.portal.AbstractPortletRunController;
import org.olat.core.gui.control.generic.portal.PortletDefaultTableDataModel;
import org.olat.core.gui.control.generic.portal.PortletEntry;
import org.olat.core.gui.control.generic.portal.PortletToolSortingControllerImpl;
import org.olat.core.gui.control.generic.portal.SortingCriteria;
import org.olat.core.gui.translator.Translator;
import org.olat.core.util.coordinate.CoordinatorManager;
import org.olat.core.util.event.GenericEventListener;
import org.olat.core.util.filter.FilterFactory;
import org.olat.core.util.resource.OresHelper;
import org.olat.group.BusinessGroup;
import org.olat.group.BusinessGroupOrder;
import org.olat.group.BusinessGroupService;
import org.olat.group.model.SearchBusinessGroupParams;
import org.olat.group.ui.edit.BusinessGroupModifiedEvent;
/**
* Description:<br>
* Run view controller for the groups list portlet
* <P>
* Initial Date: 11.07.2005 <br>
*
* @author gnaegi
*/
public class GroupsPortletRunController extends AbstractPortletRunController<BusinessGroupEntry> implements GenericEventListener {
private static final String CMD_LAUNCH = "cmd.launch";
private final TableController tableCtr;
private final GroupTableDataModel groupListModel;
private VelocityContainer groupsVC;
private Link showAllLink;
private final BusinessGroupService businessGroupService;
/**
* Constructor
*
* @param ureq
* @param component
*/
public GroupsPortletRunController(WindowControl wControl, UserRequest ureq, Translator trans,
String portletName, int defaultMaxEntries) {
super(wControl, ureq, trans, portletName, defaultMaxEntries);
businessGroupService = CoreSpringFactory.getImpl(BusinessGroupService.class);
sortingTermsList.add(SortingCriteria.ALPHABETICAL_SORTING);
sortingTermsList.add(SortingCriteria.DATE_SORTING);
groupsVC = createVelocityContainer("groupsPortlet");
showAllLink = LinkFactory.createLink("groupsPortlet.showAll", groupsVC, this);
showAllLink.setIconRightCSS("o_icon o_icon_start");
TableGuiConfiguration tableConfig = new TableGuiConfiguration();
tableConfig.setTableEmptyMessage(trans.translate("groupsPortlet.nogroups"));
tableConfig.setDisplayTableHeader(false);
tableConfig.setCustomCssClass("o_portlet_table");
tableConfig.setDisplayRowCount(false);
tableConfig.setPageingEnabled(false);
tableConfig.setDownloadOffered(false);
//disable the default sorting for this table
tableConfig.setSortingEnabled(false);
tableCtr = new TableController(tableConfig, ureq, getWindowControl(), trans);
listenTo(tableCtr);
// dummy header key, won't be used since setDisplayTableHeader is set to
// false
tableCtr.addColumnDescriptor(new DefaultColumnDescriptor("groupsPortlet.bgname", 0, CMD_LAUNCH, trans.getLocale()));
sortingCriteria = getPersistentSortingConfiguration(ureq);
groupListModel = new GroupTableDataModel(Collections.<PortletEntry<BusinessGroupEntry>>emptyList());
tableCtr.setTableDataModel(groupListModel);
reloadModel(sortingCriteria);
groupsVC.put("table", tableCtr.getInitialComponent());
putInitialPanel(groupsVC);
// register for businessgroup type events
CoordinatorManager.getInstance().getCoordinator().getEventBus().registerFor(this, ureq.getIdentity(), OresHelper.lookupType(BusinessGroup.class));
}
private List<PortletEntry<BusinessGroupEntry>> convertBusinessGroupToPortletEntryList(List<BusinessGroup> groups, boolean withDescription) {
List<PortletEntry<BusinessGroupEntry>> convertedList = new ArrayList<PortletEntry<BusinessGroupEntry>>();
for(BusinessGroup group:groups) {
GroupPortletEntry entry = new GroupPortletEntry(group);
if(withDescription) {
entry.getValue().setDescription(group.getDescription());
}
convertedList.add(entry);
}
return convertedList;
}
private List<PortletEntry<BusinessGroupEntry>> convertShortBusinessGroupToPortletEntryList(List<BusinessGroup> groups, boolean withDescription) {
List<PortletEntry<BusinessGroupEntry>> convertedList = new ArrayList<PortletEntry<BusinessGroupEntry>>();
for(BusinessGroup group:groups) {
GroupPortletEntry entry = new GroupPortletEntry(group);
if(withDescription) {
entry.getValue().setDescription(group.getDescription());
}
convertedList.add(entry);
}
return convertedList;
}
@Override
protected void reloadModel(SortingCriteria sortCriteria) {
if (sortCriteria.getSortingType() == SortingCriteria.AUTO_SORTING) {
BusinessGroupOrder order = null;
if(sortCriteria.getSortingTerm()==SortingCriteria.ALPHABETICAL_SORTING) {
order = sortCriteria.isAscending() ? BusinessGroupOrder.nameAsc : BusinessGroupOrder.nameDesc;
} else if(sortCriteria.getSortingTerm()==SortingCriteria.DATE_SORTING) {
order = sortCriteria.isAscending() ? BusinessGroupOrder.creationDateAsc : BusinessGroupOrder.creationDateDesc;
}
int maxEntries = sortCriteria.getMaxEntries();
List<BusinessGroup> groupList = businessGroupService.findBusinessGroups(getIdentity(), maxEntries * 2, order);
Set<BusinessGroup> removeDuplicates = new HashSet<BusinessGroup>(maxEntries);
for(Iterator<BusinessGroup> it=groupList.iterator(); it.hasNext(); ) {
BusinessGroup group = it.next();
if(removeDuplicates.contains(group)) {
it.remove();
} else {
removeDuplicates.add(group);
}
}
List<BusinessGroup> uniqueList = groupList.subList(0, Math.min(maxEntries, groupList.size()));
List<PortletEntry<BusinessGroupEntry>> entries = convertShortBusinessGroupToPortletEntryList(uniqueList, false);
groupListModel.setObjects(entries);
tableCtr.modelChanged();
} else {
reloadModel(getPersistentManuallySortedItems());
}
}
protected void reloadModel(List<PortletEntry<BusinessGroupEntry>> sortedItems) {
groupListModel.setObjects(sortedItems);
tableCtr.modelChanged();
}
/**
* @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest,
* org.olat.core.gui.components.Component, org.olat.core.gui.control.Event)
*/
public void event(UserRequest ureq, Component source, Event event) {
if (source == showAllLink) {
String businessPath = "[GroupsSite:0][AllGroups:0]";
NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl());
}
}
/**
* @see org.olat.core.gui.control.ControllerEventListener#dispatchEvent(org.olat.core.gui.UserRequest,
* org.olat.core.gui.control.Controller, org.olat.core.gui.control.Event)
*/
public void event(UserRequest ureq, Controller source, Event event) {
super.event(ureq, source, event);
if (source == tableCtr) {
if (event.getCommand().equals(Table.COMMANDLINK_ROWACTION_CLICKED)) {
TableEvent te = (TableEvent) event;
String actionid = te.getActionId();
if (actionid.equals(CMD_LAUNCH)) {
PortletEntry<BusinessGroupEntry> entry = groupListModel.getObject(te.getRowId());
String businessPath = "[BusinessGroup:" + entry.getKey() + "]";
NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl());
}
}
}
}
/**
* @see org.olat.core.gui.control.DefaultController#doDispose(boolean)
*/
protected void doDispose() {
super.doDispose();
// de-register for businessgroup type events
CoordinatorManager.getInstance().getCoordinator().getEventBus().deregisterFor(this, OresHelper.lookupType(BusinessGroup.class));
// POST: all firing event for the source just deregistered are finished
// (listeners lock in EventAgency)
}
public void event(Event event) {
if (event instanceof BusinessGroupModifiedEvent) {
BusinessGroupModifiedEvent mev = (BusinessGroupModifiedEvent) event;
if(BusinessGroupModifiedEvent.IDENTITY_REMOVED_EVENT.equals(event.getCommand()) &&
getIdentity().getKey().equals(mev.getAffectedIdentityKey())) {
Long modifiedKey = mev.getModifiedGroupKey();
for(PortletEntry<BusinessGroupEntry> portlet:groupListModel.getObjects()) {
if(modifiedKey.equals(portlet.getKey())) {;
groupListModel.getObjects().remove(portlet);
tableCtr.modelChanged();
break;
}
}
}
}
}
/**
* Retrieves the persistent sortingCriteria and the persistent manually sorted, if any,
* creates the table model for the manual sorting, and instantiates the PortletToolSortingControllerImpl.
* @param ureq
* @param wControl
* @return a PortletToolSortingControllerImpl instance.
*/
protected PortletToolSortingControllerImpl<BusinessGroupEntry> createSortingTool(UserRequest ureq, WindowControl wControl) {
if(portletToolsController==null) {
List<BusinessGroup> groupList = businessGroupService.findBusinessGroups(getIdentity(), -1);
List<PortletEntry<BusinessGroupEntry>> portletEntryList = convertShortBusinessGroupToPortletEntryList(groupList, true);
GroupsManualSortingTableDataModel tableDataModel = new GroupsManualSortingTableDataModel(portletEntryList);
List<PortletEntry<BusinessGroupEntry>> sortedItems = getPersistentManuallySortedItems();
portletToolsController = new PortletToolSortingControllerImpl<BusinessGroupEntry>(ureq, wControl, getTranslator(), sortingCriteria, tableDataModel, sortedItems);
portletToolsController.setConfigManualSorting(true);
portletToolsController.setConfigAutoSorting(true);
portletToolsController.addControllerListener(this);
}
return portletToolsController;
}
/**
* Retrieves the persistent manually sorted items for the current portlet.
* @param ureq
* @return
*/
private List<PortletEntry<BusinessGroupEntry>> getPersistentManuallySortedItems() {
@SuppressWarnings("unchecked")
Map<Long, Integer> storedPrefs = (Map<Long, Integer>)guiPreferences.get(Map.class, getPreferenceKey(SORTED_ITEMS_PREF));
List<PortletEntry<BusinessGroupEntry>> portletEntryList;
if(storedPrefs != null) {
SearchBusinessGroupParams params = new SearchBusinessGroupParams(getIdentity(), true, true);
params.setGroupKeys(storedPrefs.keySet());
List<BusinessGroup> groups = businessGroupService.findBusinessGroups(params, null, 0, -1);
portletEntryList = convertBusinessGroupToPortletEntryList(groups, false);
} else {
List<BusinessGroup> groups = new ArrayList<BusinessGroup>();
portletEntryList = convertShortBusinessGroupToPortletEntryList(groups, false);
}
return getPersistentManuallySortedItems(portletEntryList);
}
/**
* Comparator implementation used for sorting BusinessGroup entries according with the
* input sortingCriteria.
* <p>
* @param sortCriteria
* @return a Comparator for the input sortingCriteria
*/
protected Comparator<BusinessGroupEntry> getComparator(final SortingCriteria sortCriteria) {
return new Comparator<BusinessGroupEntry>(){
public int compare(final BusinessGroupEntry group1, final BusinessGroupEntry group2) {
int comparisonResult = 0;
if(sortCriteria.getSortingTerm()==SortingCriteria.ALPHABETICAL_SORTING) {
comparisonResult = collator.compare(group1.getName(), group2.getName());
} else if(sortCriteria.getSortingTerm()==SortingCriteria.DATE_SORTING) {
comparisonResult = group1.getCreationDate().compareTo(group2.getCreationDate());
}
if(!sortCriteria.isAscending()) {
//if not isAscending return (-comparisonResult)
return -comparisonResult;
}
return comparisonResult;
}
};
}
/**
*
* PortletDefaultTableDataModel implementation for the current portlet.
*
* <P>
* Initial Date: 10.12.2007 <br>
* @author Lavinia Dumitrescu
*/
private static class GroupTableDataModel extends PortletDefaultTableDataModel<BusinessGroupEntry> {
public GroupTableDataModel(List<PortletEntry<BusinessGroupEntry>> objects) {
super(objects, 1);
}
public Object getValueAt(int row, int col) {
PortletEntry<BusinessGroupEntry> entry = getObject(row);
BusinessGroupEntry businessGroup = entry.getValue();
switch (col) {
case 0:
return businessGroup.getName();
default:
return "ERROR";
}
}
@Override
public Object createCopyWithEmptyList() {
return new GroupTableDataModel(new ArrayList<PortletEntry<BusinessGroupEntry>>());
}
}
/**
*
* PortletDefaultTableDataModel implementation for the manual sorting component.
*
* <P>
* Initial Date: 10.12.2007 <br>
* @author Lavinia Dumitrescu
*/
private static class GroupsManualSortingTableDataModel extends PortletDefaultTableDataModel<BusinessGroupEntry> {
/**
* @param objects
* @param locale
*/
public GroupsManualSortingTableDataModel(List<PortletEntry<BusinessGroupEntry>> objects) {
super(objects, 3);
}
/**
* @see org.olat.core.gui.components.table.TableDataModel#getValueAt(int, int)
*/
public final Object getValueAt(int row, int col) {
PortletEntry<BusinessGroupEntry> portletEntry = getObject(row);
BusinessGroupEntry group = portletEntry.getValue();
switch (col) {
case 0:
return group.getName();
case 1:
String description = group.getDescription();
description = FilterFactory.getHtmlTagsFilter().filter(description);
return (description == null ? "n/a" : description);
case 2:
Date date = group.getCreationDate();
return date;
default:
return "error";
}
}
@Override
public GroupsManualSortingTableDataModel createCopyWithEmptyList() {
return new GroupsManualSortingTableDataModel(new ArrayList<PortletEntry<BusinessGroupEntry>>());
}
}
private static class GroupPortletEntry implements PortletEntry<BusinessGroupEntry> {
private BusinessGroupEntry value;
private Long key;
public GroupPortletEntry(BusinessGroup group) {
value = new BusinessGroupEntry(group);
key = group.getKey();
}
public Long getKey() {
return key;
}
public BusinessGroupEntry getValue() {
return value;
}
}
}