/** * 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.repository.ui; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import org.olat.core.CoreSpringFactory; import org.olat.core.gui.components.table.ColumnDescriptor; import org.olat.core.gui.components.table.CustomCellRenderer; import org.olat.core.gui.components.table.CustomRenderColumnDescriptor; import org.olat.core.gui.components.table.DateCellRenderer; import org.olat.core.gui.components.table.DefaultColumnDescriptor; import org.olat.core.gui.components.table.DefaultTableDataModel; import org.olat.core.gui.components.table.StaticColumnDescriptor; import org.olat.core.gui.components.table.TableController; import org.olat.core.gui.render.Renderer; import org.olat.core.gui.render.StringOutput; import org.olat.core.gui.translator.Translator; import org.olat.core.util.StringHelper; import org.olat.core.util.Util; import org.olat.login.LoginModule; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryEntryStatus; import org.olat.repository.RepositoryManager; import org.olat.repository.RepositoryModule; import org.olat.repository.RepositoryService; import org.olat.repository.manager.RepositoryEntryLifecycleDAO; import org.olat.repository.model.RepositoryEntryLifecycle; import org.olat.resource.accesscontrol.ACService; import org.olat.resource.accesscontrol.AccessControlModule; import org.olat.resource.accesscontrol.model.OLATResourceAccess; import org.olat.user.UserManager; /** * Initial Date: Mar 31, 2004 * * @author Mike Stock * * Comment: * */ public class RepositoryTableModel extends DefaultTableDataModel<RepositoryEntry> { /** * Identifies a table selection event (outer-left column) */ public static final String TABLE_ACTION_SELECT_LINK = "rtbSelectLink"; /** * Identifies a table selection event (outer-left column) */ public static final String TABLE_ACTION_REMOVE_LINK = "rtbRemoveLink"; /** * Identifies a table launch event (if clicked on an item in the name column). */ public static final String TABLE_ACTION_INFOS = "rtbInfos"; /** * Identifies a multi selection */ public static final String TABLE_ACTION_SELECT_ENTRIES = "rtbSelectEntrIES"; private static final int COLUMN_COUNT = 7; private final Translator translator; private final ACService acService; private final LoginModule loginModule; private final AccessControlModule acModule; private final RepositoryModule repositoryModule; private final RepositoryEntryLifecycleDAO lifecycleDao; private final UserManager userManager; private final Map<Long,OLATResourceAccess> repoEntriesWithOffer = new HashMap<Long,OLATResourceAccess>();; private final Map<String,String> fullNames = new HashMap<String, String>(); /** * Default constructor. * @param translator */ public RepositoryTableModel(Locale locale) { super(new ArrayList<RepositoryEntry>()); translator = Util.createPackageTranslator(RepositoryService.class, locale); acService = CoreSpringFactory.getImpl(ACService.class); loginModule = CoreSpringFactory.getImpl(LoginModule.class); userManager = CoreSpringFactory.getImpl(UserManager.class); acModule = CoreSpringFactory.getImpl(AccessControlModule.class); repositoryModule = CoreSpringFactory.getImpl(RepositoryModule.class); lifecycleDao = CoreSpringFactory.getImpl(RepositoryEntryLifecycleDAO.class); } /** * @param tableCtr * @param selectButtonLabel Label of action row or null if no action row should be used * @param enableDirectLaunch * @return the position of the display name column */ public ColumnDescriptor addColumnDescriptors(TableController tableCtr, boolean selectTitle, boolean selectIcon, boolean remove, boolean infos) { Locale loc = translator.getLocale(); CustomCellRenderer acRenderer = new RepositoryEntryACColumnDescriptor(); tableCtr.addColumnDescriptor(new CustomRenderColumnDescriptor("table.header.ac", RepoCols.ac.ordinal(), null, loc, ColumnDescriptor.ALIGNMENT_LEFT, acRenderer) { @Override public int compareTo(int rowa, int rowb) { Object o1 = table.getTableDataModel().getObject(rowa); Object o2 = table.getTableDataModel().getObject(rowb); if(o1 == null || !(o1 instanceof RepositoryEntry)) return -1; if(o2 == null || !(o2 instanceof RepositoryEntry)) return 1; RepositoryEntry re1 = (RepositoryEntry)o1; RepositoryEntry re2 = (RepositoryEntry)o2; if(re1.isMembersOnly()) { if(!re2.isMembersOnly()) { return 1; } } else if(re2.isMembersOnly()) { return -1; } OLATResourceAccess ac1 = repoEntriesWithOffer.get(re1.getOlatResource().getKey()); OLATResourceAccess ac2 = repoEntriesWithOffer.get(re2.getOlatResource().getKey()); if(ac1 == null && ac2 != null) return -1; if(ac1 != null && ac2 == null) return 1; if(ac1 != null && ac2 != null) return compareAccess(re1, ac1, re2, ac2); return super.compareString(re1.getDisplayname(), re2.getDisplayname()); } private int compareAccess(RepositoryEntry re1, OLATResourceAccess ac1, RepositoryEntry re2, OLATResourceAccess ac2) { int s1 = ac1.getMethods().size(); int s2 = ac2.getMethods().size(); int compare = s1 - s2; if(compare != 0) return compare; if(s1 > 0 && s2 > 0) { String t1 = ac1.getMethods().get(0).getMethod().getType(); String t2 = ac2.getMethods().get(0).getMethod().getType(); int compareType = super.compareString(t1, t2); if(compareType != 0) return compareType; } return super.compareString(re1.getDisplayname(), re2.getDisplayname()); } }); tableCtr.addColumnDescriptor(new RepositoryEntryTypeColumnDescriptor("table.header.typeimg", RepoCols.repoEntry.ordinal(), null, loc, ColumnDescriptor.ALIGNMENT_LEFT)); String selectAction = selectTitle ? TABLE_ACTION_SELECT_LINK : null; if(repositoryModule.isManagedRepositoryEntries()) { tableCtr.addColumnDescriptor(false, new DefaultColumnDescriptor("table.header.externalid", RepoCols.externalId.ordinal(), selectAction, loc)); tableCtr.addColumnDescriptor(new DefaultColumnDescriptor("table.header.externalref", RepoCols.externalRef.ordinal(), selectAction, loc)); } boolean lfVisible = lifecycleDao.countPublicLifecycle() > 0; tableCtr.addColumnDescriptor(lfVisible, new DefaultColumnDescriptor("table.header.lifecycle.label", RepoCols.lifecycleLabel.ordinal(), null, loc)); tableCtr.addColumnDescriptor(false, new DefaultColumnDescriptor("table.header.lifecycle.softkey", RepoCols.lifecycleSoftKey.ordinal(), null, loc)); ColumnDescriptor nameColDesc = new DefaultColumnDescriptor("table.header.displayname", RepoCols.displayname.ordinal(), selectAction, loc) { @Override public int compareTo(int rowa, int rowb) { Object o1 = table.getTableDataModel().getValueAt(rowa, 1); Object o2 = table.getTableDataModel().getValueAt(rowb, 1); if(o1 == null || !(o1 instanceof RepositoryEntry)) return -1; if(o2 == null || !(o2 instanceof RepositoryEntry)) return 1; RepositoryEntry re1 = (RepositoryEntry)o1; RepositoryEntry re2 = (RepositoryEntry)o2; boolean c1 = RepositoryManager.getInstance().createRepositoryEntryStatus(re1.getStatusCode()).isClosed(); boolean c2 = RepositoryManager.getInstance().createRepositoryEntryStatus(re2.getStatusCode()).isClosed(); int result = (c2 == c1 ? 0 : (c1 ? 1 : -1));//same as Boolean compare if(result == 0) { Object a = table.getTableDataModel().getValueAt(rowa, dataColumn); Object b = table.getTableDataModel().getValueAt(rowb, dataColumn); if(a == null || !(a instanceof String)) return -1; if(b == null || !(b instanceof String)) return 1; String s1 = (String)a; String s2 = (String)b; result = compareString(s1, s2); } return result; } }; tableCtr.addColumnDescriptor(nameColDesc); CustomCellRenderer dateRenderer = new DateCellRenderer(loc); tableCtr.addColumnDescriptor(false, new CustomRenderColumnDescriptor("table.header.lifecycle.start", RepoCols.lifecycleStart.ordinal(), null, loc, ColumnDescriptor.ALIGNMENT_LEFT, dateRenderer)); tableCtr.addColumnDescriptor(false, new CustomRenderColumnDescriptor("table.header.lifecycle.end", RepoCols.lifecycleEnd.ordinal(), null, loc, ColumnDescriptor.ALIGNMENT_LEFT, dateRenderer)); tableCtr.addColumnDescriptor(new DefaultColumnDescriptor("table.header.author", RepoCols.author.ordinal(), null, loc)); CustomCellRenderer accessRenderer = new RepositoryEntryAccessColumnDescriptor(translator); ColumnDescriptor accessColDesc = new CustomRenderColumnDescriptor("table.header.access", RepoCols.repoEntry.ordinal(), null, loc, ColumnDescriptor.ALIGNMENT_LEFT, accessRenderer) { @Override public int compareTo(int rowa, int rowb) { Object o1 = table.getTableDataModel().getValueAt(rowa, 1); Object o2 = table.getTableDataModel().getValueAt(rowb, 1); if(o1 == null || !(o1 instanceof RepositoryEntry)) return -1; if(o2 == null || !(o2 instanceof RepositoryEntry)) return 1; RepositoryEntry re1 = (RepositoryEntry)o1; RepositoryEntry re2 = (RepositoryEntry)o2; int ar1 = re1.getAccess(); if(re1.isMembersOnly()) { ar1 = 99; } int ar2 = re2.getAccess(); if(re2.isMembersOnly()) { ar2 = 99; } if(ar1 < ar2) return -1; if(ar1 > ar2) return 1; return super.compareString(re1.getDisplayname(), re2.getDisplayname()); } }; tableCtr.addColumnDescriptor(accessColDesc); tableCtr.addColumnDescriptor(false, new DefaultColumnDescriptor("table.header.date", RepoCols.creationDate.ordinal(), null, loc)); tableCtr.addColumnDescriptor(false, new DefaultColumnDescriptor("table.header.lastusage", RepoCols.lastUsage.ordinal(), null, loc)); if(infos) { tableCtr.addColumnDescriptor(new StaticColumnDescriptor(TABLE_ACTION_INFOS, "info.header", translator.translate("info.header")){ @Override public void renderValue(StringOutput so, int row, Renderer renderer) { so.append("<i id='o_core").append(row).append("ref' class='o_icon o_icon-lg o_icon_info_resource'> </i>"); } }); } if(selectIcon) { tableCtr.addColumnDescriptor(new StaticColumnDescriptor(TABLE_ACTION_SELECT_LINK, "select", translator.translate("table.select"))); } if(remove) { tableCtr.addColumnDescriptor(new StaticColumnDescriptor(TABLE_ACTION_REMOVE_LINK, "remove", translator.translate("remove"))); } return nameColDesc; } /** * @see org.olat.core.gui.components.table.TableDataModel#getColumnCount() */ @Override public int getColumnCount() { return COLUMN_COUNT; } /** * @see org.olat.core.gui.components.table.TableDataModel#getValueAt(int, int) */ @Override public Object getValueAt(int row, int col) { RepositoryEntry re = getObject(row); switch (RepoCols.values()[col]) { case ac: { if (re.isMembersOnly()) { // members only always show lock icon List<String> types = new ArrayList<String>(1); types.add("o_ac_membersonly"); return types; } OLATResourceAccess access = repoEntriesWithOffer.get(re.getOlatResource().getKey()); if(access == null) { return null; } return access; } case repoEntry: return re; case displayname: return getDisplayName(re, translator.getLocale()); case author: return getFullname(re.getInitialAuthor()); case access: { if(re.isMembersOnly()) { return translator.translate("table.header.access.membersonly"); } switch (re.getAccess()) { case RepositoryEntry.ACC_OWNERS: return translator.translate("table.header.access.owner"); case RepositoryEntry.ACC_OWNERS_AUTHORS: return translator.translate("table.header.access.author"); case RepositoryEntry.ACC_USERS: return translator.translate("table.header.access.user"); case RepositoryEntry.ACC_USERS_GUESTS: { if(!loginModule.isGuestLoginLinksEnabled()) { return translator.translate("table.header.access.user"); } return translator.translate("table.header.access.guest"); } default: // OLAT-6272 in case of broken repo entries with no access code // return error instead of nothing return "ERROR"; } } case creationDate: return re.getCreationDate(); case lastUsage: return re.getStatistics().getLastUsage(); case externalId: return re.getExternalId(); case externalRef: return re.getExternalRef(); case lifecycleLabel: { RepositoryEntryLifecycle lf = re.getLifecycle(); if(lf == null || lf.isPrivateCycle()) { return ""; } return lf.getLabel(); } case lifecycleSoftKey: { RepositoryEntryLifecycle lf = re.getLifecycle(); if(lf == null || lf.isPrivateCycle()) { return ""; } return lf.getSoftKey(); } case lifecycleStart: return re.getLifecycle() == null ? null : re.getLifecycle().getValidFrom(); case lifecycleEnd: return re.getLifecycle() == null ? null : re.getLifecycle().getValidTo(); default: return "ERROR"; } } public enum RepoCols { ac, repoEntry, displayname, author, access, creationDate, lastUsage, externalId, externalRef, lifecycleLabel, lifecycleSoftKey, lifecycleStart, lifecycleEnd } @Override public void setObjects(List<RepositoryEntry> objects) { super.setObjects(objects); repoEntriesWithOffer.clear(); secondaryInformations(objects); } public void addObject(RepositoryEntry object) { getObjects().add(object); secondaryInformations(Collections.singletonList(object)); } public void addObjects(List<RepositoryEntry> addedObjects) { getObjects().addAll(addedObjects); secondaryInformations(addedObjects); } private void secondaryInformations(List<RepositoryEntry> repoEntries) { if(repoEntries == null || repoEntries.isEmpty()) return; secondaryInformationsAccessControl(repoEntries); secondaryInformationsUsernames(repoEntries); } private void secondaryInformationsAccessControl(List<RepositoryEntry> repoEntries) { if(repoEntries == null || repoEntries.isEmpty() || !acModule.isEnabled()) return; List<OLATResourceAccess> withOffers = acService.filterRepositoryEntriesWithAC(repoEntries); for(OLATResourceAccess withOffer:withOffers) { repoEntriesWithOffer.put(withOffer.getResource().getKey(), withOffer); } } private void secondaryInformationsUsernames(List<RepositoryEntry> repoEntries) { if(repoEntries == null || repoEntries.isEmpty()) return; Set<String> newNames = new HashSet<String>(); for(RepositoryEntry re:repoEntries) { final String author = re.getInitialAuthor(); if(StringHelper.containsNonWhitespace(author) && !fullNames.containsKey(author)) { newNames.add(author); } } if(!newNames.isEmpty()) { Map<String,String> newFullnames = userManager.getUserDisplayNamesByUserName(newNames); fullNames.putAll(newFullnames); } } public void removeObject(RepositoryEntry object) { getObjects().remove(object); repoEntriesWithOffer.remove(object.getOlatResource().getKey()); } private String getFullname(String author) { if(fullNames.containsKey(author)) { return fullNames.get(author); } return author; } /** * Get displayname of a repository entry. If repository entry a course * and is this course closed then add a prefix to the title. */ private String getDisplayName(RepositoryEntry repositoryEntry, Locale locale) { String displayName = repositoryEntry.getDisplayname(); if (repositoryEntry != null && repositoryEntry.getRepositoryEntryStatus().isClosed()) { Translator pT = Util.createPackageTranslator(RepositoryEntryStatus.class, locale); displayName = "[" + pT.translate("title.prefix.closed") + "] ".concat(displayName); } return displayName; } @Override public Object createCopyWithEmptyList() { RepositoryTableModel copy = new RepositoryTableModel(translator.getLocale()); return copy; } }