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