001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: https://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: https://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.ui.apps.user; 029 030import org.opencms.file.CmsGroup; 031import org.opencms.file.CmsObject; 032import org.opencms.main.CmsException; 033import org.opencms.main.CmsLog; 034import org.opencms.main.OpenCms; 035import org.opencms.security.CmsRole; 036import org.opencms.security.CmsRoleViolationException; 037import org.opencms.ui.A_CmsUI; 038import org.opencms.ui.CmsCssIcon; 039import org.opencms.ui.CmsVaadinUtils; 040import org.opencms.ui.apps.Messages; 041import org.opencms.ui.components.CmsBasicDialog; 042import org.opencms.ui.components.CmsBasicDialog.DialogWidth; 043import org.opencms.ui.components.OpenCmsTheme; 044import org.opencms.ui.contextmenu.CmsContextMenu; 045import org.opencms.ui.contextmenu.CmsMenuItemVisibilityMode; 046import org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry; 047import org.opencms.util.CmsStringUtil; 048import org.opencms.util.CmsUUID; 049 050import java.util.ArrayList; 051import java.util.HashSet; 052import java.util.List; 053import java.util.Locale; 054import java.util.Set; 055 056import org.apache.commons.logging.Log; 057 058import com.vaadin.server.Resource; 059import com.vaadin.shared.MouseEventDetails.MouseButton; 060import com.vaadin.ui.Window; 061import com.vaadin.ui.themes.ValoTheme; 062import com.vaadin.v7.data.Item; 063import com.vaadin.v7.data.util.IndexedContainer; 064import com.vaadin.v7.data.util.filter.Or; 065import com.vaadin.v7.data.util.filter.SimpleStringFilter; 066import com.vaadin.v7.event.ItemClickEvent; 067import com.vaadin.v7.event.ItemClickEvent.ItemClickListener; 068import com.vaadin.v7.ui.Table; 069import com.vaadin.v7.ui.VerticalLayout; 070 071/** 072 * Class for the table containing groups of a ou.<p> 073 */ 074public class CmsGroupTable extends Table implements I_CmsFilterableTable, I_CmsToggleTable { 075 076 /**Table properties.<p>*/ 077 public enum TableProperty { 078 079 /**Desription column. */ 080 Description(CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_GROUP_DESCRIPTION_0), String.class, ""), 081 /**Icon column.*/ 082 Icon(null, Resource.class, new CmsCssIcon(OpenCmsTheme.ICON_GROUP)), 083 /**IsIndirect?. */ 084 INDIRECT("", Boolean.class, Boolean.valueOf(false)), 085 /**Name column. */ 086 Name(CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_GROUP_NAME_0), String.class, ""), 087 /**OU column. */ 088 OU(CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_GROUP_OU_0), String.class, ""); 089 090 /**Default value for column.*/ 091 private Object m_defaultValue; 092 093 /**Header Message key.*/ 094 private String m_headerMessage; 095 096 /**Type of column property.*/ 097 private Class<?> m_type; 098 099 /** 100 * constructor.<p> 101 * 102 * @param name Name 103 * @param type type 104 * @param defaultValue value 105 */ 106 TableProperty(String name, Class<?> type, Object defaultValue) { 107 108 m_headerMessage = name; 109 m_type = type; 110 m_defaultValue = defaultValue; 111 } 112 113 /** 114 * The default value.<p> 115 * 116 * @return the default value object 117 */ 118 Object getDefault() { 119 120 return m_defaultValue; 121 } 122 123 /** 124 * Gets the name of the property.<p> 125 * 126 * @return a name 127 */ 128 String getName() { 129 130 return m_headerMessage; 131 132 } 133 134 /** 135 * Gets the type of property.<p> 136 * 137 * @return the type 138 */ 139 Class<?> getType() { 140 141 return m_type; 142 } 143 144 } 145 146 /** 147 * Delete context menu entry.<p> 148 */ 149 class EntryDelete implements I_CmsSimpleContextMenuEntry<Set<String>> { 150 151 /** 152 * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#executeAction(java.lang.Object) 153 */ 154 public void executeAction(final Set<String> context) { 155 156 Window window = CmsBasicDialog.prepareWindow(); 157 CmsDeleteMultiplePrincipalDialog dialog = new CmsDeleteMultiplePrincipalDialog( 158 m_cms, 159 context, 160 window, 161 m_app); 162 window.setContent(dialog); 163 window.setCaption(CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_GROUP_DELETE_0)); 164 A_CmsUI.get().addWindow(window); 165 } 166 167 /** 168 * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#getTitle(java.util.Locale) 169 */ 170 public String getTitle(Locale locale) { 171 172 return CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_GROUP_DELETE_0); 173 } 174 175 /** 176 * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#getVisibility(java.lang.Object) 177 */ 178 public CmsMenuItemVisibilityMode getVisibility(Set<String> context) { 179 180 boolean ok = canDelete(context); 181 return ok ? CmsMenuItemVisibilityMode.VISIBILITY_ACTIVE : CmsMenuItemVisibilityMode.VISIBILITY_INACTIVE; 182 } 183 184 } 185 186 /** 187 * Edit context menu entry.<p> 188 */ 189 class EntryEdit implements I_CmsSimpleContextMenuEntry<Set<String>> { 190 191 /** 192 * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#executeAction(java.lang.Object) 193 */ 194 public void executeAction(Set<String> context) { 195 196 Window window = CmsBasicDialog.prepareWindow(); 197 window.setCaption(CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_EDIT_GROUP_0)); 198 window.setContent(new CmsGroupEditDialog(m_cms, new CmsUUID(context.iterator().next()), window, m_app)); 199 200 A_CmsUI.get().addWindow(window); 201 } 202 203 /** 204 * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#getTitle(java.util.Locale) 205 */ 206 public String getTitle(Locale locale) { 207 208 return CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_EDIT_GROUP_0); 209 } 210 211 /** 212 * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#getVisibility(java.lang.Object) 213 */ 214 public CmsMenuItemVisibilityMode getVisibility(Set<String> context) { 215 216 if (context.size() > 1) { 217 return CmsMenuItemVisibilityMode.VISIBILITY_INACTIVE; 218 } 219 return CmsMenuItemVisibilityMode.VISIBILITY_ACTIVE; 220 } 221 222 } 223 224 /** 225 * Open entry for context menu.<p> 226 */ 227 class EntryOpen implements I_CmsSimpleContextMenuEntry<Set<String>>, I_CmsSimpleContextMenuEntry.I_HasCssStyles { 228 229 /** 230 * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#executeAction(java.lang.Object) 231 */ 232 public void executeAction(Set<String> context) { 233 234 updateApp(context.iterator().next()); 235 } 236 237 /** 238 * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry.I_HasCssStyles#getStyles() 239 */ 240 public String getStyles() { 241 242 return ValoTheme.LABEL_BOLD; 243 } 244 245 /** 246 * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#getTitle(java.util.Locale) 247 */ 248 public String getTitle(Locale locale) { 249 250 return CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_OPEN_0); 251 } 252 253 /** 254 * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#getVisibility(java.lang.Object) 255 */ 256 public CmsMenuItemVisibilityMode getVisibility(Set<String> context) { 257 258 if (context.size() > 1) { 259 return CmsMenuItemVisibilityMode.VISIBILITY_INACTIVE; 260 } 261 if (m_app != null) { 262 return CmsMenuItemVisibilityMode.VISIBILITY_ACTIVE; 263 } else { 264 return CmsMenuItemVisibilityMode.VISIBILITY_INVISIBLE; 265 } 266 } 267 268 } 269 270 /** 271 * Show resources context menu entry.<p> 272 */ 273 class EntryShowResources implements I_CmsSimpleContextMenuEntry<Set<String>> { 274 275 /** 276 * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#executeAction(java.lang.Object) 277 */ 278 public void executeAction(Set<String> context) { 279 280 Window window = CmsBasicDialog.prepareWindow(DialogWidth.wide); 281 window.setCaption(CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_SHOW_RESOURCES_0)); 282 window.setContent(new CmsShowResourcesDialog(context.iterator().next(), window)); 283 284 A_CmsUI.get().addWindow(window); 285 } 286 287 /** 288 * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#getTitle(java.util.Locale) 289 */ 290 public String getTitle(Locale locale) { 291 292 return CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_SHOW_RESOURCES_0); 293 } 294 295 /** 296 * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#getVisibility(java.lang.Object) 297 */ 298 public CmsMenuItemVisibilityMode getVisibility(Set<String> context) { 299 300 if (context.size() > 1) { 301 return CmsMenuItemVisibilityMode.VISIBILITY_INACTIVE; 302 } 303 return CmsMenuItemVisibilityMode.VISIBILITY_ACTIVE; 304 } 305 306 } 307 308 /** 309 * Show resources context menu entry.<p> 310 */ 311 class ImExport implements I_CmsSimpleContextMenuEntry<Set<String>> { 312 313 /** 314 * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#executeAction(java.lang.Object) 315 */ 316 public void executeAction(Set<String> context) { 317 318 boolean includeTechnicalFields = false; 319 try { 320 OpenCms.getRoleManager().checkRole(m_cms, CmsRole.ADMINISTRATOR); 321 includeTechnicalFields = true; 322 } catch (CmsRoleViolationException e) { 323 // ok 324 } 325 Window window = CmsBasicDialog.prepareWindow(DialogWidth.wide); 326 window.setCaption(CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_USER_IMEXPORT_DIALOGNAME_0)); 327 window.setContent( 328 CmsImportExportUserDialog.getExportUserDialogForGroup( 329 new CmsUUID(context.iterator().next()), 330 m_ou, 331 window, 332 includeTechnicalFields)); 333 334 A_CmsUI.get().addWindow(window); 335 } 336 337 /** 338 * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#getTitle(java.util.Locale) 339 */ 340 public String getTitle(Locale locale) { 341 342 return CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_USER_IMEXPORT_CONTEXTMENUNAME_0); 343 } 344 345 /** 346 * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#getVisibility(java.lang.Object) 347 */ 348 public CmsMenuItemVisibilityMode getVisibility(Set<String> context) { 349 350 return CmsMenuItemVisibilityMode.activeInactive(canImportData(context)); 351 352 } 353 354 } 355 356 /** Log instance for this class. */ 357 private static final Log LOG = CmsLog.getLog(CmsGroupTable.class); 358 359 /**vaadin serial id. */ 360 private static final long serialVersionUID = -6511159488669996003L; 361 362 /**Calling app. */ 363 protected CmsAccountsApp m_app; 364 365 /**The ou. */ 366 protected String m_ou; 367 368 /**CmsObject. */ 369 CmsObject m_cms; 370 371 /**List of groups. */ 372 List<CmsGroup> m_groups; 373 374 /**List of indirect groups. */ 375 List<CmsGroup> m_indirects; 376 377 /** The context menu. */ 378 CmsContextMenu m_menu; 379 380 /**Indexed container. */ 381 private IndexedContainer m_container; 382 383 /**Vaadin component. */ 384 private VerticalLayout m_emptyLayout; 385 386 /**flag indicates if all indirect items (for sub OUs) are loaded. */ 387 private boolean m_fullLoaded; 388 389 /** The available menu entries. */ 390 private List<I_CmsSimpleContextMenuEntry<Set<String>>> m_menuEntries; 391 392 /** The tree type. */ 393 private I_CmsOuTreeType m_type; 394 395 /** 396 * public constructor.<p> 397 * 398 * @param ou ou name 399 * @param app calling app. 400 * @param type the tree type 401 * @param showAll if all groups should be shown 402 */ 403 public CmsGroupTable(String ou, CmsAccountsApp app, I_CmsOuTreeType type, boolean showAll) { 404 405 m_app = app; 406 m_ou = ou; 407 m_type = type; 408 m_indirects = new ArrayList<CmsGroup>(); 409 List<CmsGroup> directs; 410 try { 411 m_cms = OpenCms.initCmsObject(A_CmsUI.getCmsObject()); 412 m_cms.getRequestContext().setSiteRoot(""); 413 } catch (CmsException e) { 414 m_cms = A_CmsUI.getCmsObject(); 415 } 416 try { 417 directs = m_app.readGroupsForOu(m_cms, ou, m_type, false); 418 m_fullLoaded = false; 419 if (showAll) { 420 setAllGroups(directs); 421 } else { 422 m_groups = directs; 423 } 424 } catch (CmsException e) { 425 // TODO Auto-generated catch block 426 e.printStackTrace(); 427 } 428 init(ou); 429 430 } 431 432 /** 433 * Fills the container item representing a group.<p> 434 * 435 * @param item the item 436 * @param group the group 437 * @param indirects the indirect groups 438 */ 439 public void fillGroupItem(Item item, CmsGroup group, List<CmsGroup> indirects) { 440 441 item.getItemProperty(TableProperty.Name).setValue(group.getName()); 442 item.getItemProperty(TableProperty.Description).setValue(group.getDescription(A_CmsUI.get().getLocale())); 443 item.getItemProperty(TableProperty.OU).setValue(group.getOuFqn()); 444 if (indirects.contains(group)) { 445 item.getItemProperty(TableProperty.INDIRECT).setValue(Boolean.TRUE); 446 } 447 } 448 449 /** 450 * Filters the table.<p> 451 * 452 * @see org.opencms.ui.apps.user.I_CmsFilterableTable#filter(java.lang.String) 453 */ 454 public void filter(String data) { 455 456 m_container.removeAllContainerFilters(); 457 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(data)) { 458 m_container.addContainerFilter( 459 new Or( 460 new SimpleStringFilter(TableProperty.Name, data, true, false), 461 new SimpleStringFilter(TableProperty.Description, data, true, false))); 462 } 463 464 } 465 466 /** 467 * @see org.opencms.ui.apps.user.I_CmsToggleTable#getCurrentSize() 468 */ 469 public int getCurrentSize() { 470 471 return size(); 472 } 473 474 /** 475 * @see org.opencms.ui.apps.user.I_CmsFilterableTable#getEmptyLayout() 476 */ 477 public VerticalLayout getEmptyLayout() { 478 479 m_emptyLayout = CmsVaadinUtils.getInfoLayout(CmsOuTreeType.GROUP.getEmptyMessageKey()); 480 setVisible(size() > 0); 481 m_emptyLayout.setVisible(size() == 0); 482 return m_emptyLayout; 483 } 484 485 /** 486 * @see org.opencms.ui.apps.user.I_CmsToggleTable#toggle(boolean) 487 */ 488 public void toggle(boolean pressed) { 489 490 try { 491 if (pressed && !m_fullLoaded) { 492 setAllGroups(m_groups); 493 } 494 } catch (CmsException e) { 495 LOG.error("Error loading groups", e); 496 } 497 fillContainer(pressed); 498 } 499 500 /** 501 * Returns true if the given group can be deleted.<p> 502 * 503 * @param groupIds the set of groups 504 * @return true if the set of groups can be deleted 505 */ 506 protected boolean canDelete(Set<String> groupIds) { 507 508 return true; 509 } 510 511 /** 512 * Return true if the CSV import should be enabled for a set of groups 513 * 514 * @param groupIds the set of group ids 515 * 516 * @return true if the CSV import should be enabled 517 */ 518 protected boolean canImportData(Set<String> groupIds) { 519 520 return groupIds.size() == 1; 521 } 522 523 /** 524 * Fills the container.<p> 525 * 526 * @param showIndirect true-> show all user, false -> only direct user 527 */ 528 protected void fillContainer(boolean showIndirect) { 529 530 m_container.removeAllContainerFilters(); 531 m_container.removeAllItems(); 532 for (CmsGroup group : m_groups) { 533 if (!m_indirects.contains(group)) { 534 Item item = m_container.addItem(group); 535 m_app.fillGroupItem(item, group, m_indirects); 536 } 537 } 538 if (showIndirect) { 539 for (CmsGroup group : m_indirects) { 540 Item item = m_container.addItem(group); 541 m_app.fillGroupItem(item, group, m_indirects); 542 } 543 } 544 } 545 546 /** 547 * Initializes the table.<p> 548 * 549 * @param ou name 550 */ 551 protected void init(String ou) { 552 553 m_menu = new CmsContextMenu(); 554 m_menu.setAsTableContextMenu(this); 555 556 m_container = new IndexedContainer(); 557 558 for (TableProperty prop : TableProperty.values()) { 559 m_container.addContainerProperty(prop, prop.getType(), prop.getDefault()); 560 setColumnHeader(prop, prop.getName()); 561 } 562 m_app.addGroupContainerProperties(m_container); 563 setContainerDataSource(m_container); 564 setItemIconPropertyId(TableProperty.Icon); 565 setRowHeaderMode(RowHeaderMode.ICON_ONLY); 566 567 setColumnWidth(null, 40); 568 setSelectable(true); 569 setMultiSelect(true); 570 571 for (CmsGroup group : m_groups) { 572 Item item = m_container.addItem(group); 573 m_app.fillGroupItem(item, group, m_indirects); 574 } 575 576 addItemClickListener(new ItemClickListener() { 577 578 private static final long serialVersionUID = 4807195510202231174L; 579 580 @SuppressWarnings("unchecked") 581 public void itemClick(ItemClickEvent event) { 582 583 changeValueIfNotMultiSelect(event.getItemId()); 584 585 if (event.getButton().equals(MouseButton.RIGHT) || (event.getPropertyId() == null)) { 586 Set<String> groupIds = new HashSet<String>(); 587 for (CmsGroup group : (Set<CmsGroup>)getValue()) { 588 groupIds.add(group.getId().getStringValue()); 589 } 590 m_menu.setEntries(getMenuEntries(), groupIds); 591 m_menu.openForTable(event, event.getItemId(), event.getPropertyId(), CmsGroupTable.this); 592 return; 593 } 594 if (event.getButton().equals(MouseButton.LEFT) && event.getPropertyId().equals(TableProperty.Name)) { 595 updateApp((((Set<CmsGroup>)getValue()).iterator().next()).getId().getStringValue()); 596 } 597 } 598 599 }); 600 setCellStyleGenerator(new CellStyleGenerator() { 601 602 private static final long serialVersionUID = 1L; 603 604 public String getStyle(Table source, Object itemId, Object propertyId) { 605 606 String css = ""; 607 if (((Boolean)source.getItem(itemId).getItemProperty( 608 TableProperty.INDIRECT).getValue()).booleanValue()) { 609 css += " " + OpenCmsTheme.TABLE_CELL_DISABLED + " " + OpenCmsTheme.EXPIRED; 610 } 611 if (TableProperty.Name.equals(propertyId)) { 612 css += " " + OpenCmsTheme.HOVER_COLUMN; 613 } 614 615 return css; 616 } 617 }); 618 setVisibleColumns(TableProperty.Name, TableProperty.Description, TableProperty.OU); 619 } 620 621 /** 622 * Updates the app.<p> 623 * 624 * @param uuid of current group 625 */ 626 protected void updateApp(String uuid) { 627 628 try { 629 CmsGroup group = m_cms.readGroup(new CmsUUID(uuid)); 630 m_app.update(group.getOuFqn(), m_type, group.getId(), ""); 631 } catch (CmsException e) { 632 LOG.error("unable to read group.", e); 633 } 634 } 635 636 /** 637 * Checks value of table and sets it new if needed:<p> 638 * if multiselect: new itemId is in current Value? -> no change of value<p> 639 * no multiselect and multiselect, but new item not selected before: set value to new item<p> 640 * 641 * @param itemId if of clicked item 642 */ 643 void changeValueIfNotMultiSelect(Object itemId) { 644 645 @SuppressWarnings("unchecked") 646 Set<String> value = (Set<String>)getValue(); 647 if (value == null) { 648 select(itemId); 649 } else if (!value.contains(itemId)) { 650 setValue(null); 651 select(itemId); 652 } 653 } 654 655 /** 656 * Returns the available menu entries.<p> 657 * 658 * @return the menu entries 659 */ 660 List<I_CmsSimpleContextMenuEntry<Set<String>>> getMenuEntries() { 661 662 if (m_menuEntries == null) { 663 m_menuEntries = new ArrayList<I_CmsSimpleContextMenuEntry<Set<String>>>(); 664 m_menuEntries.add(new EntryOpen()); 665 m_menuEntries.add(new EntryEdit()); 666 m_menuEntries.add(new EntryShowResources()); 667 m_menuEntries.add(new ImExport()); 668 m_menuEntries.add(new EntryDelete()); 669 670 } 671 return m_menuEntries; 672 } 673 674 /** 675 * Sets all groups.<p> 676 * 677 * @param directs the direct groups 678 * 679 * @throws CmsException if something goes wrong 680 */ 681 private void setAllGroups(List<CmsGroup> directs) throws CmsException { 682 683 m_fullLoaded = true; 684 m_groups = m_app.readGroupsForOu(m_cms, m_ou, m_type, true); 685 m_indirects.clear(); 686 for (CmsGroup group : m_groups) { 687 if (!directs.contains(group)) { 688 m_indirects.add(group); 689 } 690 } 691 692 } 693 694}