001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (C) Alkacon Software (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.components; 029 030import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_CACHE; 031import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_CATEGORIES; 032import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_COPYRIGHT; 033import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_DATE_CREATED; 034import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_DATE_EXPIRED; 035import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_DATE_MODIFIED; 036import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_DATE_RELEASED; 037import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_INSIDE_PROJECT; 038import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_INTERNAL_RESOURCE_TYPE; 039import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_IN_NAVIGATION; 040import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_IS_FOLDER; 041import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_NAVIGATION_POSITION; 042import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_NAVIGATION_TEXT; 043import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_PERMISSIONS; 044import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_PROJECT; 045import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_RELEASED_NOT_EXPIRED; 046import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_RESOURCE_NAME; 047import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_RESOURCE_TYPE; 048import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_SIZE; 049import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_STATE; 050import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_STATE_NAME; 051import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_TITLE; 052import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_TYPE_ICON; 053import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_USER_CREATED; 054import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_USER_LOCKED; 055import static org.opencms.ui.components.CmsResourceTableProperty.PROPERTY_USER_MODIFIED; 056 057import org.opencms.db.CmsResourceState; 058import org.opencms.file.CmsObject; 059import org.opencms.file.CmsResource; 060import org.opencms.file.CmsResourceFilter; 061import org.opencms.file.CmsVfsResourceNotFoundException; 062import org.opencms.main.CmsException; 063import org.opencms.main.CmsLog; 064import org.opencms.main.OpenCms; 065import org.opencms.ui.A_CmsUI; 066import org.opencms.ui.CmsVaadinUtils; 067import org.opencms.ui.I_CmsDialogContext; 068import org.opencms.ui.I_CmsEditPropertyContext; 069import org.opencms.ui.actions.I_CmsDefaultAction; 070import org.opencms.ui.apps.CmsFileExplorerSettings; 071import org.opencms.ui.apps.I_CmsContextProvider; 072import org.opencms.ui.contextmenu.CmsContextMenu; 073import org.opencms.ui.contextmenu.CmsResourceContextMenuBuilder; 074import org.opencms.ui.contextmenu.I_CmsContextMenuBuilder; 075import org.opencms.ui.util.I_CmsItemSorter; 076import org.opencms.util.CmsStringUtil; 077import org.opencms.util.CmsUUID; 078 079import java.io.ByteArrayOutputStream; 080import java.io.OutputStreamWriter; 081import java.nio.charset.StandardCharsets; 082import java.text.DateFormat; 083import java.text.SimpleDateFormat; 084import java.util.ArrayList; 085import java.util.Arrays; 086import java.util.Collection; 087import java.util.Collections; 088import java.util.Date; 089import java.util.HashSet; 090import java.util.LinkedHashMap; 091import java.util.List; 092import java.util.Locale; 093import java.util.Map; 094import java.util.Map.Entry; 095import java.util.Set; 096import java.util.TimeZone; 097 098import org.apache.commons.logging.Log; 099 100import com.google.common.base.Function; 101import com.google.common.collect.Lists; 102import com.vaadin.event.FieldEvents.BlurEvent; 103import com.vaadin.event.FieldEvents.BlurListener; 104import com.vaadin.event.ShortcutAction.KeyCode; 105import com.vaadin.event.ShortcutListener; 106import com.vaadin.shared.MouseEventDetails.MouseButton; 107import com.vaadin.shared.Registration; 108import com.vaadin.ui.Component; 109import com.vaadin.ui.themes.ValoTheme; 110import com.vaadin.v7.data.Container; 111import com.vaadin.v7.data.Container.Filter; 112import com.vaadin.v7.data.Item; 113import com.vaadin.v7.data.Property.ValueChangeEvent; 114import com.vaadin.v7.data.Property.ValueChangeListener; 115import com.vaadin.v7.data.util.DefaultItemSorter; 116import com.vaadin.v7.data.util.IndexedContainer; 117import com.vaadin.v7.data.util.filter.Or; 118import com.vaadin.v7.data.util.filter.SimpleStringFilter; 119import com.vaadin.v7.event.ItemClickEvent; 120import com.vaadin.v7.event.ItemClickEvent.ItemClickListener; 121import com.vaadin.v7.ui.AbstractTextField.TextChangeEventMode; 122import com.vaadin.v7.ui.DefaultFieldFactory; 123import com.vaadin.v7.ui.Field; 124import com.vaadin.v7.ui.Table; 125import com.vaadin.v7.ui.Table.TableDragMode; 126import com.vaadin.v7.ui.TextField; 127 128import au.com.bytecode.opencsv.CSVWriter; 129 130/** 131 * Table for displaying resources.<p> 132 */ 133public class CmsFileTable extends CmsResourceTable { 134 135 /** 136 * File edit handler.<p> 137 */ 138 public class FileEditHandler implements BlurListener { 139 140 /** The serial version id. */ 141 private static final long serialVersionUID = -2286815522247807054L; 142 143 /** 144 * @see com.vaadin.event.FieldEvents.BlurListener#blur(com.vaadin.event.FieldEvents.BlurEvent) 145 */ 146 public void blur(BlurEvent event) { 147 148 stopEdit(); 149 } 150 } 151 152 /** 153 * Field factory to enable inline editing of individual file properties.<p> 154 */ 155 public class FileFieldFactory extends DefaultFieldFactory { 156 157 /** The serial version id. */ 158 private static final long serialVersionUID = 3079590603587933576L; 159 160 /** 161 * @see com.vaadin.v7.ui.DefaultFieldFactory#createField(com.vaadin.v7.data.Container, java.lang.Object, java.lang.Object, com.vaadin.ui.Component) 162 */ 163 @Override 164 public Field<?> createField(Container container, Object itemId, Object propertyId, Component uiContext) { 165 166 Field<?> result = null; 167 if (itemId.equals(getEditItemId().toString()) && isEditProperty((CmsResourceTableProperty)propertyId)) { 168 result = super.createField(container, itemId, propertyId, uiContext); 169 result.addStyleName(OpenCmsTheme.INLINE_TEXTFIELD); 170 result.addValidator(m_editHandler); 171 if (result instanceof TextField) { 172 ((TextField)result).setComponentError(null); 173 clearColumnEditActions(); 174 // we attach the shortcuts to the table, not the textbox, so that they still trigger if the change from the edited field would cause the current row 175 // to be filtered by the current container filter. 176 m_columnEditEscRegistration = CmsFileTable.this.addShortcutListener( 177 new ShortcutListener("Cancel edit", KeyCode.ESCAPE, null) { 178 179 private static final long serialVersionUID = 1L; 180 181 @Override 182 public void handleAction(Object sender, Object target) { 183 184 cancelEdit(); 185 } 186 }); 187 188 m_columnEditEnterRegistration = CmsFileTable.this.addShortcutListener( 189 new ShortcutListener("Save", KeyCode.ENTER, null) { 190 191 private static final long serialVersionUID = 1L; 192 193 @Override 194 public void handleAction(Object sender, Object target) { 195 196 stopEdit(); 197 } 198 }); 199 200 ((TextField)result).addBlurListener(m_fileEditHandler); 201 ((TextField)result).setTextChangeEventMode(TextChangeEventMode.LAZY); 202 ((TextField)result).addTextChangeListener(m_editHandler); 203 } 204 result.focus(); 205 } 206 return result; 207 } 208 } 209 210 /** 211 * Extends the default sorting to differentiate between files and folder when sorting by name.<p> 212 * Also allows sorting by navPos property for the Resource icon column.<p> 213 */ 214 public static class FileSorter extends DefaultItemSorter implements I_CmsItemSorter { 215 216 /** The serial version id. */ 217 private static final long serialVersionUID = 1L; 218 219 /** 220 * @see org.opencms.ui.util.I_CmsItemSorter#getSortableContainerPropertyIds(com.vaadin.v7.data.Container) 221 */ 222 public Collection<?> getSortableContainerPropertyIds(Container container) { 223 224 Set<Object> result = new HashSet<Object>(); 225 for (Object propId : container.getContainerPropertyIds()) { 226 Class<?> propertyType = container.getType(propId); 227 if (Comparable.class.isAssignableFrom(propertyType) 228 || propertyType.isPrimitive() 229 || (propId.equals(CmsResourceTableProperty.PROPERTY_TYPE_ICON) 230 && container.getContainerPropertyIds().contains( 231 CmsResourceTableProperty.PROPERTY_NAVIGATION_POSITION))) { 232 result.add(propId); 233 } 234 } 235 return result; 236 } 237 238 /** 239 * @see com.vaadin.v7.data.util.DefaultItemSorter#compareProperty(java.lang.Object, boolean, com.vaadin.v7.data.Item, com.vaadin.v7.data.Item) 240 */ 241 @Override 242 protected int compareProperty(Object propertyId, boolean sortDirection, Item item1, Item item2) { 243 244 //@formatter:off 245 if (CmsResourceTableProperty.PROPERTY_RESOURCE_NAME.equals(propertyId)) { 246 Boolean isFolder1 = (Boolean)item1.getItemProperty( 247 CmsResourceTableProperty.PROPERTY_IS_FOLDER).getValue(); 248 Boolean isFolder2 = (Boolean)item2.getItemProperty( 249 CmsResourceTableProperty.PROPERTY_IS_FOLDER).getValue(); 250 if (!isFolder1.equals(isFolder2)) { 251 int result = isFolder1.booleanValue() ? -1 : 1; 252 if (!sortDirection) { 253 result = result * (-1); 254 } 255 return result; 256 } 257 } else if ((CmsResourceTableProperty.PROPERTY_TYPE_ICON.equals(propertyId) 258 || CmsResourceTableProperty.PROPERTY_NAVIGATION_TEXT.equals(propertyId)) 259 && (item1.getItemProperty(CmsResourceTableProperty.PROPERTY_NAVIGATION_POSITION) != null)) { 260 int result; 261 Float pos1 = (Float)item1.getItemProperty( 262 CmsResourceTableProperty.PROPERTY_NAVIGATION_POSITION).getValue(); 263 Float pos2 = (Float)item2.getItemProperty( 264 CmsResourceTableProperty.PROPERTY_NAVIGATION_POSITION).getValue(); 265 if (pos1 == null) { 266 result = pos2 == null 267 ? compareProperty(CmsResourceTableProperty.PROPERTY_RESOURCE_NAME, true, item1, item2) 268 : 1; 269 } else { 270 result = pos2 == null ? -1 : Float.compare(pos1.floatValue(), pos2.floatValue()); 271 } 272 if (!sortDirection) { 273 result = result * (-1); 274 } 275 return result; 276 } 277 278 if (((CmsResourceTableProperty)propertyId).getColumnType().equals(String.class)) { 279 String value1 = (String)item1.getItemProperty(propertyId).getValue(); 280 String value2 = (String)item2.getItemProperty(propertyId).getValue(); 281 // Java collators obtained by java.text.Collator.getInstance(...) ignore spaces, and we don't want to ignore them, so we use 282 // ICU collators instead 283 com.ibm.icu.text.Collator collator = com.ibm.icu.text.Collator.getInstance( 284 com.ibm.icu.util.ULocale.ROOT); 285 int result = collator.compare(value1, value2); 286 if (!sortDirection) { 287 result = -result; 288 } 289 return result; 290 } 291 return super.compareProperty(propertyId, sortDirection, item1, item2); 292 //@formatter:on 293 } 294 } 295 296 /** 297 * Handles folder selects in the file table.<p> 298 */ 299 public interface I_FolderSelectHandler { 300 301 /** 302 * Called when the folder name is left clicked.<p> 303 * 304 * @param folderId the selected folder id 305 */ 306 void onFolderSelect(CmsUUID folderId); 307 } 308 309 /** The default file table columns. */ 310 public static final Map<CmsResourceTableProperty, Integer> DEFAULT_TABLE_PROPERTIES; 311 312 /** The logger instance for this class. */ 313 static final Log LOG = CmsLog.getLog(CmsFileTable.class); 314 315 /** The serial version id. */ 316 private static final long serialVersionUID = 5460048685141699277L; 317 318 static { 319 Map<CmsResourceTableProperty, Integer> defaultProps = new LinkedHashMap<CmsResourceTableProperty, Integer>(); 320 defaultProps.put(PROPERTY_TYPE_ICON, Integer.valueOf(0)); 321 defaultProps.put(PROPERTY_PROJECT, Integer.valueOf(COLLAPSED)); 322 defaultProps.put(PROPERTY_RESOURCE_NAME, Integer.valueOf(0)); 323 defaultProps.put(PROPERTY_TITLE, Integer.valueOf(0)); 324 try { 325 if (OpenCms.getWorkplaceManager().isExplorerCategoriesEnabled()) { 326 defaultProps.put(PROPERTY_CATEGORIES, Integer.valueOf(COLLAPSED)); 327 } 328 } catch (Exception e) { 329 // ignore 330 } 331 defaultProps.put(PROPERTY_NAVIGATION_TEXT, Integer.valueOf(COLLAPSED)); 332 defaultProps.put(PROPERTY_NAVIGATION_POSITION, Integer.valueOf(INVISIBLE)); 333 defaultProps.put(PROPERTY_IN_NAVIGATION, Integer.valueOf(INVISIBLE)); 334 defaultProps.put(PROPERTY_COPYRIGHT, Integer.valueOf(COLLAPSED)); 335 defaultProps.put(PROPERTY_CACHE, Integer.valueOf(COLLAPSED)); 336 defaultProps.put(PROPERTY_RESOURCE_TYPE, Integer.valueOf(0)); 337 defaultProps.put(PROPERTY_INTERNAL_RESOURCE_TYPE, Integer.valueOf(COLLAPSED)); 338 defaultProps.put(PROPERTY_SIZE, Integer.valueOf(0)); 339 defaultProps.put(PROPERTY_PERMISSIONS, Integer.valueOf(COLLAPSED)); 340 defaultProps.put(PROPERTY_DATE_MODIFIED, Integer.valueOf(0)); 341 defaultProps.put(PROPERTY_USER_MODIFIED, Integer.valueOf(COLLAPSED)); 342 defaultProps.put(PROPERTY_DATE_CREATED, Integer.valueOf(COLLAPSED)); 343 defaultProps.put(PROPERTY_USER_CREATED, Integer.valueOf(COLLAPSED)); 344 defaultProps.put(PROPERTY_DATE_RELEASED, Integer.valueOf(0)); 345 defaultProps.put(PROPERTY_DATE_EXPIRED, Integer.valueOf(0)); 346 defaultProps.put(PROPERTY_STATE_NAME, Integer.valueOf(0)); 347 defaultProps.put(PROPERTY_USER_LOCKED, Integer.valueOf(0)); 348 defaultProps.put(PROPERTY_IS_FOLDER, Integer.valueOf(INVISIBLE)); 349 defaultProps.put(PROPERTY_STATE, Integer.valueOf(INVISIBLE)); 350 defaultProps.put(PROPERTY_INSIDE_PROJECT, Integer.valueOf(INVISIBLE)); 351 defaultProps.put(PROPERTY_RELEASED_NOT_EXPIRED, Integer.valueOf(INVISIBLE)); 352 DEFAULT_TABLE_PROPERTIES = Collections.unmodifiableMap(defaultProps); 353 } 354 355 /** The selected resources. */ 356 protected List<CmsResource> m_currentResources = new ArrayList<CmsResource>(); 357 358 /** The default action column property. */ 359 CmsResourceTableProperty m_actionColumnProperty; 360 361 /** The additional cell style generators. */ 362 List<Table.CellStyleGenerator> m_additionalStyleGenerators; 363 364 /** The current file property edit handler. */ 365 I_CmsFilePropertyEditHandler m_editHandler; 366 367 /** File edit event handler. */ 368 FileEditHandler m_fileEditHandler = new FileEditHandler(); 369 370 /** The context menu. */ 371 CmsContextMenu m_menu; 372 373 /** The context menu builder. */ 374 I_CmsContextMenuBuilder m_menuBuilder; 375 376 /** The table drag mode, stored during item editing. */ 377 private TableDragMode m_beforEditDragMode; 378 379 /** Action registration for pressing Enter during column editing. */ 380 private Registration m_columnEditEnterRegistration; 381 382 /** Action registration for pressing Esc during column editing. */ 383 private Registration m_columnEditEscRegistration; 384 385 /** The dialog context provider. */ 386 private I_CmsContextProvider m_contextProvider; 387 388 /** The edited item id. */ 389 private CmsUUID m_editItemId; 390 391 /** The edited property id. */ 392 private CmsResourceTableProperty m_editProperty; 393 394 /** Stack of saved container filters. */ 395 private List<Collection<Filter>> m_filterStack = new ArrayList<>(); 396 397 /** The folder select handler. */ 398 private I_FolderSelectHandler m_folderSelectHandler; 399 400 /** The original edit value. */ 401 private String m_originalEditValue; 402 403 /** 404 * Default constructor.<p> 405 * 406 * @param contextProvider the dialog context provider 407 */ 408 public CmsFileTable(I_CmsContextProvider contextProvider) { 409 410 this(contextProvider, DEFAULT_TABLE_PROPERTIES); 411 } 412 413 /** 414 * Default constructor.<p> 415 * 416 * @param contextProvider the dialog context provider 417 * @param tableColumns the table columns to show 418 */ 419 public CmsFileTable(I_CmsContextProvider contextProvider, Map<CmsResourceTableProperty, Integer> tableColumns) { 420 421 super(); 422 m_additionalStyleGenerators = new ArrayList<Table.CellStyleGenerator>(); 423 m_actionColumnProperty = PROPERTY_RESOURCE_NAME; 424 m_contextProvider = contextProvider; 425 m_container.setItemSorter(new FileSorter()); 426 m_fileTable.addStyleName(ValoTheme.TABLE_BORDERLESS); 427 m_fileTable.addStyleName(OpenCmsTheme.SIMPLE_DRAG); 428 m_fileTable.setSizeFull(); 429 m_fileTable.setColumnCollapsingAllowed(true); 430 m_fileTable.setSelectable(true); 431 m_fileTable.setMultiSelect(true); 432 433 m_fileTable.setTableFieldFactory(new FileFieldFactory()); 434 ColumnBuilder builder = new ColumnBuilder(); 435 for (Entry<CmsResourceTableProperty, Integer> entry : tableColumns.entrySet()) { 436 builder.column(entry.getKey(), entry.getValue().intValue()); 437 } 438 builder.buildColumns(); 439 440 m_fileTable.setSortContainerPropertyId(CmsResourceTableProperty.PROPERTY_RESOURCE_NAME); 441 m_menu = new CmsContextMenu(); 442 m_fileTable.addValueChangeListener(new ValueChangeListener() { 443 444 private static final long serialVersionUID = 1L; 445 446 public void valueChange(ValueChangeEvent event) { 447 448 @SuppressWarnings("unchecked") 449 Set<String> selectedIds = (Set<String>)event.getProperty().getValue(); 450 List<CmsResource> selectedResources = new ArrayList<CmsResource>(); 451 for (String id : selectedIds) { 452 try { 453 CmsResource resource = A_CmsUI.getCmsObject().readResource( 454 getUUIDFromItemID(id), 455 CmsResourceFilter.ALL); 456 selectedResources.add(resource); 457 } catch (CmsException e) { 458 LOG.error(e.getLocalizedMessage(), e); 459 } 460 461 } 462 m_currentResources = selectedResources; 463 464 rebuildMenu(); 465 } 466 }); 467 468 m_fileTable.addItemClickListener(new ItemClickListener() { 469 470 private static final long serialVersionUID = 1L; 471 472 public void itemClick(ItemClickEvent event) { 473 474 handleFileItemClick(event); 475 } 476 }); 477 478 m_fileTable.setCellStyleGenerator(new Table.CellStyleGenerator() { 479 480 private static final long serialVersionUID = 1L; 481 482 public String getStyle(Table source, Object itemId, Object propertyId) { 483 484 Item item = m_container.getItem(itemId); 485 String style = getStateStyle(item); 486 if (m_actionColumnProperty == propertyId) { 487 style += " " + OpenCmsTheme.HOVER_COLUMN; 488 } else if ((CmsResourceTableProperty.PROPERTY_NAVIGATION_TEXT == propertyId) 489 || (CmsResourceTableProperty.PROPERTY_TITLE == propertyId)) { 490 if ((item.getItemProperty(CmsResourceTableProperty.PROPERTY_IN_NAVIGATION) != null) 491 && ((Boolean)item.getItemProperty( 492 CmsResourceTableProperty.PROPERTY_IN_NAVIGATION).getValue()).booleanValue()) { 493 style += " " + OpenCmsTheme.IN_NAVIGATION; 494 } 495 } 496 for (Table.CellStyleGenerator generator : m_additionalStyleGenerators) { 497 String additional = generator.getStyle(source, itemId, propertyId); 498 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(additional)) { 499 style += " " + additional; 500 } 501 } 502 return style; 503 } 504 }); 505 506 m_menu.setAsTableContextMenu(m_fileTable); 507 } 508 509 /** 510 * Returns the resource state specific style name.<p> 511 * 512 * @param resourceItem the resource item 513 * 514 * @return the style name 515 */ 516 public static String getStateStyle(Item resourceItem) { 517 518 String result = ""; 519 if (resourceItem != null) { 520 if ((resourceItem.getItemProperty(PROPERTY_INSIDE_PROJECT) == null) 521 || ((Boolean)resourceItem.getItemProperty(PROPERTY_INSIDE_PROJECT).getValue()).booleanValue()) { 522 523 CmsResourceState state = (CmsResourceState)resourceItem.getItemProperty( 524 CmsResourceTableProperty.PROPERTY_STATE).getValue(); 525 result = getStateStyle(state); 526 } else { 527 result = OpenCmsTheme.PROJECT_OTHER; 528 } 529 if ((resourceItem.getItemProperty(PROPERTY_RELEASED_NOT_EXPIRED) != null) 530 && !((Boolean)resourceItem.getItemProperty(PROPERTY_RELEASED_NOT_EXPIRED).getValue()).booleanValue()) { 531 result += " " + OpenCmsTheme.EXPIRED; 532 } 533 if ((resourceItem.getItemProperty(CmsResourceTableProperty.PROPERTY_DISABLED) != null) 534 && ((Boolean)resourceItem.getItemProperty( 535 CmsResourceTableProperty.PROPERTY_DISABLED).getValue()).booleanValue()) { 536 result += " " + OpenCmsTheme.DISABLED; 537 } 538 } 539 return result; 540 } 541 542 /** 543 * Adds an additional cell style generator.<p> 544 * 545 * @param styleGenerator the cell style generator 546 */ 547 public void addAdditionalStyleGenerator(Table.CellStyleGenerator styleGenerator) { 548 549 m_additionalStyleGenerators.add(styleGenerator); 550 } 551 552 /** 553 * Applies settings generally used within workplace app file lists.<p> 554 */ 555 public void applyWorkplaceAppSettings() { 556 557 // add site path property to container 558 m_container.addContainerProperty( 559 CmsResourceTableProperty.PROPERTY_SITE_PATH, 560 CmsResourceTableProperty.PROPERTY_SITE_PATH.getColumnType(), 561 CmsResourceTableProperty.PROPERTY_SITE_PATH.getDefaultValue()); 562 563 // replace the resource name column with the path column 564 Object[] visibleCols = m_fileTable.getVisibleColumns(); 565 for (int i = 0; i < visibleCols.length; i++) { 566 if (CmsResourceTableProperty.PROPERTY_RESOURCE_NAME.equals(visibleCols[i])) { 567 visibleCols[i] = CmsResourceTableProperty.PROPERTY_SITE_PATH; 568 } 569 } 570 m_fileTable.setVisibleColumns(visibleCols); 571 m_fileTable.setColumnCollapsible(CmsResourceTableProperty.PROPERTY_SITE_PATH, false); 572 m_fileTable.setColumnHeader( 573 CmsResourceTableProperty.PROPERTY_SITE_PATH, 574 CmsVaadinUtils.getMessageText(CmsResourceTableProperty.PROPERTY_SITE_PATH.getHeaderKey())); 575 576 // update column visibility according to the latest file explorer settings 577 CmsFileExplorerSettings settings; 578 try { 579 settings = OpenCms.getWorkplaceAppManager().getAppSettings( 580 A_CmsUI.getCmsObject(), 581 CmsFileExplorerSettings.class); 582 583 setTableState(settings); 584 } catch (Exception e) { 585 LOG.error("Error while reading file explorer settings from user.", e); 586 } 587 m_fileTable.setSortContainerPropertyId(CmsResourceTableProperty.PROPERTY_SITE_PATH); 588 setActionColumnProperty(CmsResourceTableProperty.PROPERTY_SITE_PATH); 589 setMenuBuilder(new CmsResourceContextMenuBuilder()); 590 } 591 592 /** 593 * Clears all container filters. 594 */ 595 public void clearFilters() { 596 597 IndexedContainer container = (IndexedContainer)m_fileTable.getContainerDataSource(); 598 container.removeAllContainerFilters(); 599 } 600 601 /** 602 * Checks if the file table has a row for the resource with the given structure id. 603 * 604 * @param structureId a structure id 605 * @return true if the file table has a row for the resource with the given id 606 */ 607 public boolean containsId(CmsUUID structureId) { 608 609 return m_fileTable.getContainerDataSource().getItem("" + structureId) != null; 610 } 611 612 /** 613 * Filters the displayed resources.<p> 614 * Only resources where either the resource name, the title or the nav-text contains the given substring are shown.<p> 615 * 616 * @param search the search term 617 */ 618 public void filterTable(String search) { 619 620 m_container.removeAllContainerFilters(); 621 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(search)) { 622 m_container.addContainerFilter( 623 new Or( 624 new SimpleStringFilter(CmsResourceTableProperty.PROPERTY_RESOURCE_NAME, search, true, false), 625 new SimpleStringFilter(CmsResourceTableProperty.PROPERTY_NAVIGATION_TEXT, search, true, false), 626 new SimpleStringFilter(CmsResourceTableProperty.PROPERTY_TITLE, search, true, false), 627 new SimpleStringFilter(CmsResourceTableProperty.PROPERTY_CATEGORIES, search, true, false))); 628 } 629 if ((m_fileTable.getValue() != null) & !((Set<?>)m_fileTable.getValue()).isEmpty()) { 630 m_fileTable.setCurrentPageFirstItemId(((Set<?>)m_fileTable.getValue()).iterator().next()); 631 } 632 } 633 634 /** 635 * Generates UTF-8 encoded CSV for currently active table columns (standard columns only). 636 * 637 * <p>Note: the generated CSV takes the active filters into account. 638 * 639 * @return the generated CSV data 640 */ 641 public byte[] generateCsv() { 642 643 try { 644 Container container = m_fileTable.getContainerDataSource(); 645 Object[] columnArray = m_fileTable.getVisibleColumns(); 646 Set<Object> columns = new HashSet<>(Arrays.asList(columnArray)); 647 LinkedHashMap<Object, Function<Object, String>> columnFormatters = new LinkedHashMap<>(); 648 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 649 CSVWriter writer = new CSVWriter(new OutputStreamWriter(baos, StandardCharsets.UTF_8)); 650 List<String> csvHeaders = new ArrayList<>(); 651 List<CmsResourceTableProperty> csvColumns = new ArrayList<>(); 652 653 for (Object propId : m_fileTable.getVisibleColumns()) { 654 if (propId instanceof CmsResourceTableProperty) { 655 CmsResourceTableProperty tableProp = (CmsResourceTableProperty)propId; 656 if (!m_fileTable.isColumnCollapsed(propId)) { 657 Class<?> colType = tableProp.getColumnType(); 658 // skip columns with Vaadin types - currently this is just the project flag 659 if (!colType.getName().contains("vaadin")) { 660 // always use English column headers, as external tools using the CSV may use the column labels as IDs 661 String colHeader = OpenCms.getWorkplaceManager().getMessages(Locale.ENGLISH).key( 662 tableProp.getHeaderKey()); 663 csvHeaders.add(colHeader); 664 csvColumns.add(tableProp); 665 } 666 } 667 } 668 } 669 670 final String[] emptyArray = {}; 671 writer.writeNext(csvHeaders.toArray(emptyArray)); 672 final DateFormat iso8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); 673 iso8601.setTimeZone(TimeZone.getTimeZone("UTC")); 674 675 Set<CmsResourceTableProperty> dateCols = new HashSet<>( 676 Arrays.asList( 677 CmsResourceTableProperty.PROPERTY_DATE_CREATED, 678 CmsResourceTableProperty.PROPERTY_DATE_MODIFIED, 679 CmsResourceTableProperty.PROPERTY_DATE_RELEASED, 680 CmsResourceTableProperty.PROPERTY_DATE_EXPIRED)); 681 for (Object itemId : m_fileTable.getContainerDataSource().getItemIds()) { 682 Item item = m_fileTable.getContainerDataSource().getItem(itemId); 683 List<String> row = new ArrayList<>(); 684 for (CmsResourceTableProperty col : csvColumns) { 685 Object value = item.getItemProperty(col).getValue(); 686 // render nulls as empty strings, some special "Long"-valued date columns as ISO8601 time stamps, and just use toString() for everything else 687 String csvValue = ""; 688 if (value != null) { 689 if (dateCols.contains(col) && (value instanceof Long)) { 690 csvValue = iso8601.format(new Date((Long)value)); 691 } else { 692 csvValue = value.toString(); 693 } 694 } 695 row.add(csvValue); 696 } 697 writer.writeNext(row.toArray(emptyArray)); 698 } 699 writer.flush(); 700 byte[] result = baos.toByteArray(); 701 return result; 702 } catch (Exception e) { 703 LOG.error(e.getLocalizedMessage(), e); 704 return null; 705 } 706 } 707 708 /** 709 * Returns the dialog context provider.<p> 710 * 711 * @return the dialog context provider 712 */ 713 public I_CmsContextProvider getContextProvider() { 714 715 return m_contextProvider; 716 } 717 718 /** 719 * Returns the index of the first visible item.<p> 720 * 721 * @return the first visible item 722 */ 723 public int getFirstVisibleItemIndex() { 724 725 return m_fileTable.getCurrentPageFirstItemIndex(); 726 } 727 728 /** 729 * Gets the selected structure ids.<p> 730 * 731 * @return the set of selected structure ids 732 */ 733 @SuppressWarnings("unchecked") 734 public Collection<CmsUUID> getSelectedIds() { 735 736 return itemIdsToUUIDs((Collection<String>)m_fileTable.getValue()); 737 } 738 739 /** 740 * Gets the list of selected resources.<p> 741 * 742 * @return the list of selected resources 743 */ 744 public List<CmsResource> getSelectedResources() { 745 746 return m_currentResources; 747 } 748 749 /** 750 * Returns the current table state.<p> 751 * 752 * @return the table state 753 */ 754 public CmsFileExplorerSettings getTableSettings() { 755 756 CmsFileExplorerSettings fileTableState = new CmsFileExplorerSettings(); 757 758 fileTableState.setSortAscending(m_fileTable.isSortAscending()); 759 fileTableState.setSortColumnId((CmsResourceTableProperty)m_fileTable.getSortContainerPropertyId()); 760 List<CmsResourceTableProperty> collapsedCollumns = new ArrayList<>(); 761 List<CmsResourceTableProperty> uncollapsedColumns = new ArrayList<>(); 762 Object[] visibleCols = m_fileTable.getVisibleColumns(); 763 for (int i = 0; i < visibleCols.length; i++) { 764 if (m_fileTable.isColumnCollapsed(visibleCols[i])) { 765 collapsedCollumns.add((CmsResourceTableProperty)visibleCols[i]); 766 } else { 767 uncollapsedColumns.add((CmsResourceTableProperty)visibleCols[i]); 768 } 769 } 770 fileTableState.setCollapsedColumns(collapsedCollumns); 771 fileTableState.setUncollapsedColumns(uncollapsedColumns); 772 return fileTableState; 773 } 774 775 /** 776 * Handles the item selection.<p> 777 * 778 * @param itemId the selected item id 779 */ 780 public void handleSelection(String itemId) { 781 782 Collection<?> selection = (Collection<?>)m_fileTable.getValue(); 783 if (selection == null) { 784 m_fileTable.select(itemId); 785 } else if (!selection.contains(itemId)) { 786 m_fileTable.setValue(null); 787 m_fileTable.select(itemId); 788 } 789 } 790 791 /** 792 * Returns if a file property is being edited.<p> 793 * @return <code>true</code> if a file property is being edited 794 */ 795 public boolean isEditing() { 796 797 return m_editItemId != null; 798 } 799 800 /** 801 * Returns if the given property is being edited.<p> 802 * 803 * @param propertyId the property id 804 * 805 * @return <code>true</code> if the given property is being edited 806 */ 807 public boolean isEditProperty(CmsResourceTableProperty propertyId) { 808 809 return (m_editProperty != null) && m_editProperty.equals(propertyId); 810 } 811 812 /** 813 * Opens the context menu.<p> 814 * 815 * @param event the click event 816 */ 817 public void openContextMenu(ItemClickEvent event) { 818 819 m_menu.openForTable(event, m_fileTable); 820 } 821 822 /** 823 * Removes the given cell style generator.<p> 824 * 825 * @param styleGenerator the cell style generator to remove 826 */ 827 public void removeAdditionalStyleGenerator(Table.CellStyleGenerator styleGenerator) { 828 829 m_additionalStyleGenerators.remove(styleGenerator); 830 } 831 832 /** 833 * Restores container filters to the ones previously saved via saveFilters(). 834 */ 835 public void restoreFilters() { 836 837 if (m_filterStack.size() > 0) { 838 IndexedContainer container = (IndexedContainer)m_fileTable.getContainerDataSource(); 839 container.removeAllContainerFilters(); 840 Collection<Filter> filters = m_filterStack.remove(m_filterStack.size() - 1); 841 for (Filter filter : filters) { 842 container.addContainerFilter(filter); 843 } 844 } else { 845 LOG.error("restoreFilter called but no saved filters available"); 846 } 847 } 848 849 /** 850 * Saves currently active filters.<p> 851 */ 852 public void saveFilters() { 853 854 IndexedContainer container = (IndexedContainer)m_fileTable.getContainerDataSource(); 855 Collection<Filter> filters = container.getContainerFilters(); 856 m_filterStack.add(new ArrayList<>(filters)); // we need to make a copy because the list returned by getContainerFilters() is changed dynamically by the container 857 } 858 859 /** 860 * Sets the default action column property.<p> 861 * 862 * @param actionColumnProperty the default action column property 863 */ 864 public void setActionColumnProperty(CmsResourceTableProperty actionColumnProperty) { 865 866 m_actionColumnProperty = actionColumnProperty; 867 } 868 869 /** 870 * Sets the dialog context provider.<p> 871 * 872 * @param provider the dialog context provider 873 */ 874 public void setContextProvider(I_CmsContextProvider provider) { 875 876 m_contextProvider = provider; 877 } 878 879 /** 880 * Sets the first visible item index.<p> 881 * 882 * @param i the item index 883 */ 884 public void setFirstVisibleItemIndex(int i) { 885 886 m_fileTable.setCurrentPageFirstItemIndex(i); 887 } 888 889 /** 890 * Sets the folder select handler.<p> 891 * 892 * @param folderSelectHandler the folder select handler 893 */ 894 public void setFolderSelectHandler(I_FolderSelectHandler folderSelectHandler) { 895 896 m_folderSelectHandler = folderSelectHandler; 897 } 898 899 /** 900 * Sets the menu builder.<p> 901 * 902 * @param builder the menu builder 903 */ 904 public void setMenuBuilder(I_CmsContextMenuBuilder builder) { 905 906 m_menuBuilder = builder; 907 } 908 909 /** 910 * Sets the table state.<p> 911 * 912 * @param state the table state 913 */ 914 public void setTableState(CmsFileExplorerSettings state) { 915 916 if (state != null) { 917 m_fileTable.setSortContainerPropertyId(state.getSortColumnId()); 918 m_fileTable.setSortAscending(state.isSortAscending()); 919 Object[] visibleCols = m_fileTable.getVisibleColumns(); 920 for (int i = 0; i < visibleCols.length; i++) { 921 if (!CmsFileTable.DEFAULT_TABLE_PROPERTIES.containsKey(visibleCols[i])) { 922 // custom column defined in a subclass - ignore it, leaving the collapse state as it currently is 923 continue; 924 } 925 boolean isCollapsed; 926 // Originally, just the collapsed columns would be stored in the user settings. 927 // The problem with this is that if new columns were added in a new version of OpenCms, 928 // those would be active by default for users who had stored table settings. 929 // So we now also store the uncollapsed columns, and prioritize this list for deciding whether 930 // a column should be visible. 931 if (state.getUncollapsedColumns() != null) { 932 isCollapsed = !state.getUncollapsedColumns().contains(visibleCols[i]); 933 } else { 934 isCollapsed = state.getCollapsedColumns().contains(visibleCols[i]) 935 || CmsResourceTableProperty.PROPERTY_CATEGORIES.equals(visibleCols[i]); 936 } 937 if (m_fileTable.isColumnCollapsible(visibleCols[i])) { 938 m_fileTable.setColumnCollapsed(visibleCols[i], isCollapsed); 939 } else { 940 LOG.debug("Skip collapsing none-collapsible column " + visibleCols[i]); 941 } 942 } 943 } 944 } 945 946 /** 947 * Starts inline editing of the given file property.<p> 948 * 949 * @param itemId the item resource structure id 950 * @param propertyId the property to edit 951 * @param editHandler the edit handler 952 */ 953 public void startEdit( 954 CmsUUID itemId, 955 CmsResourceTableProperty propertyId, 956 I_CmsFilePropertyEditHandler editHandler) { 957 958 m_editItemId = itemId; 959 m_editProperty = propertyId; 960 m_originalEditValue = (String)m_container.getItem(m_editItemId.toString()).getItemProperty( 961 m_editProperty).getValue(); 962 m_editHandler = editHandler; 963 964 // storing current drag mode and setting it to none to avoid text selection issues in IE11 965 m_beforEditDragMode = m_fileTable.getDragMode(); 966 m_fileTable.setDragMode(TableDragMode.NONE); 967 968 m_fileTable.setEditable(true); 969 } 970 971 /** 972 * Stops the current edit process to save the changed property value.<p> 973 */ 974 public void stopEdit() { 975 976 if (m_editHandler != null) { 977 saveFilters(); 978 clearFilters(); 979 try { 980 String value = (String)m_container.getItem(m_editItemId.toString()).getItemProperty( 981 m_editProperty).getValue(); 982 if (!value.equals(m_originalEditValue)) { 983 m_editHandler.validate(value); 984 m_editHandler.save(value); 985 } else { 986 // call cancel to ensure unlock 987 m_editHandler.cancel(); 988 } 989 } finally { 990 restoreFilters(); 991 } 992 } 993 clearEdit(); 994 995 // restoring drag mode 996 m_fileTable.setDragMode(m_beforEditDragMode); 997 998 m_beforEditDragMode = null; 999 } 1000 1001 /** 1002 * Updates all items with ids from the given list.<p> 1003 * 1004 * @param ids the resource structure ids to update 1005 * @param remove true if the item should be removed only 1006 */ 1007 public void update(Collection<CmsUUID> ids, boolean remove) { 1008 1009 for (CmsUUID id : ids) { 1010 updateItem(id, remove); 1011 } 1012 rebuildMenu(); 1013 } 1014 1015 /** 1016 * Updates the column widths.<p> 1017 * 1018 * The reason this is needed is that the Vaadin table does not support minimum widths for columns, 1019 * so expanding columns get squished when most of the horizontal space is used by other columns. 1020 * So we try to determine whether the expanded columns would have enough space, and if not, give them a 1021 * fixed width. 1022 * 1023 * @param estimatedSpace the estimated horizontal space available for the table. 1024 */ 1025 public void updateColumnWidths(int estimatedSpace) { 1026 1027 Object[] cols = m_fileTable.getVisibleColumns(); 1028 List<CmsResourceTableProperty> expandCols = Lists.newArrayList(); 1029 int nonExpandWidth = 0; 1030 int totalExpandMinWidth = 0; 1031 for (Object colObj : cols) { 1032 if (m_fileTable.isColumnCollapsed(colObj)) { 1033 continue; 1034 } 1035 CmsResourceTableProperty prop = (CmsResourceTableProperty)colObj; 1036 if (0 < m_fileTable.getColumnExpandRatio(prop)) { 1037 expandCols.add(prop); 1038 totalExpandMinWidth += getAlternativeWidthForExpandingColumns(prop); 1039 } else { 1040 nonExpandWidth += prop.getColumnWidth(); 1041 } 1042 } 1043 if (estimatedSpace < (totalExpandMinWidth + nonExpandWidth)) { 1044 for (CmsResourceTableProperty expandCol : expandCols) { 1045 m_fileTable.setColumnWidth(expandCol, getAlternativeWidthForExpandingColumns(expandCol)); 1046 } 1047 } 1048 } 1049 1050 /** 1051 * Updates the file table sorting.<p> 1052 */ 1053 public void updateSorting() { 1054 1055 m_fileTable.sort(); 1056 } 1057 1058 /** 1059 * Cancels the current edit process.<p> 1060 */ 1061 void cancelEdit() { 1062 1063 if (m_editHandler != null) { 1064 m_editHandler.cancel(); 1065 } 1066 clearEdit(); 1067 } 1068 1069 /** 1070 * Returns the edit item id.<p> 1071 * 1072 * @return the edit item id 1073 */ 1074 CmsUUID getEditItemId() { 1075 1076 return m_editItemId; 1077 } 1078 1079 /** 1080 * Returns the edit property id.<p> 1081 * 1082 * @return the edit property id 1083 */ 1084 CmsResourceTableProperty getEditProperty() { 1085 1086 return m_editProperty; 1087 } 1088 1089 /** 1090 * Handles the file table item click.<p> 1091 * 1092 * @param event the click event 1093 */ 1094 void handleFileItemClick(ItemClickEvent event) { 1095 1096 if (isEditing()) { 1097 stopEdit(); 1098 1099 } else if (!event.isCtrlKey() && !event.isShiftKey()) { 1100 // don't interfere with multi-selection using control key 1101 String itemId = (String)event.getItemId(); 1102 CmsUUID structureId = getUUIDFromItemID(itemId); 1103 boolean openedFolder = false; 1104 if (event.getButton().equals(MouseButton.RIGHT)) { 1105 handleSelection(itemId); 1106 openContextMenu(event); 1107 } else { 1108 if ((event.getPropertyId() == null) 1109 || CmsResourceTableProperty.PROPERTY_TYPE_ICON.equals(event.getPropertyId())) { 1110 handleSelection(itemId); 1111 openContextMenu(event); 1112 } else { 1113 if (m_actionColumnProperty.equals(event.getPropertyId())) { 1114 Boolean isFolder = (Boolean)event.getItem().getItemProperty( 1115 CmsResourceTableProperty.PROPERTY_IS_FOLDER).getValue(); 1116 if ((isFolder != null) && isFolder.booleanValue()) { 1117 if (m_folderSelectHandler != null) { 1118 m_folderSelectHandler.onFolderSelect(structureId); 1119 } 1120 openedFolder = true; 1121 } else { 1122 try { 1123 CmsObject cms = A_CmsUI.getCmsObject(); 1124 CmsResource res = cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION); 1125 m_currentResources = Collections.singletonList(res); 1126 I_CmsDialogContext context = m_contextProvider.getDialogContext(); 1127 I_CmsDefaultAction action = OpenCms.getWorkplaceAppManager().getDefaultAction( 1128 context, 1129 m_menuBuilder); 1130 if (action != null) { 1131 action.executeAction(context); 1132 return; 1133 } 1134 } catch (CmsVfsResourceNotFoundException e) { 1135 LOG.info(e.getLocalizedMessage(), e); 1136 } catch (CmsException e) { 1137 LOG.error(e.getLocalizedMessage(), e); 1138 } 1139 } 1140 } else { 1141 I_CmsDialogContext context = m_contextProvider.getDialogContext(); 1142 if ((m_currentResources.size() == 1) 1143 && m_currentResources.get(0).getStructureId().equals(structureId) 1144 && (context instanceof I_CmsEditPropertyContext) 1145 && ((I_CmsEditPropertyContext)context).isPropertyEditable(event.getPropertyId())) { 1146 1147 ((I_CmsEditPropertyContext)context).editProperty(event.getPropertyId()); 1148 } 1149 } 1150 } 1151 } 1152 // update the item on click to show any available changes 1153 if (!openedFolder) { 1154 update(Collections.singletonList(structureId), false); 1155 } 1156 } 1157 } 1158 1159 /** 1160 * Rebuilds the context menu.<p> 1161 */ 1162 void rebuildMenu() { 1163 1164 if (!getSelectedIds().isEmpty() && (m_menuBuilder != null)) { 1165 m_menu.removeAllItems(); 1166 m_menuBuilder.buildContextMenu(getContextProvider().getDialogContext(), m_menu); 1167 } 1168 } 1169 1170 /** 1171 * Clears the actions that were set for editing a column. 1172 */ 1173 private void clearColumnEditActions() { 1174 1175 if (m_columnEditEnterRegistration != null) { 1176 m_columnEditEnterRegistration.remove(); 1177 m_columnEditEnterRegistration = null; 1178 } 1179 if (m_columnEditEscRegistration != null) { 1180 m_columnEditEscRegistration.remove(); 1181 m_columnEditEscRegistration = null; 1182 } 1183 } 1184 1185 /** 1186 * Clears the current edit process.<p> 1187 */ 1188 private void clearEdit() { 1189 1190 m_fileTable.setEditable(false); 1191 if (m_editItemId != null) { 1192 try { 1193 // current filter may prevent item from being updated 1194 saveFilters(); 1195 clearFilters(); 1196 updateItem(m_editItemId, false); 1197 } finally { 1198 restoreFilters(); 1199 } 1200 } 1201 m_editItemId = null; 1202 m_editProperty = null; 1203 m_editHandler = null; 1204 clearColumnEditActions(); 1205 updateSorting(); 1206 } 1207 1208 /** 1209 * Gets alternative width for expanding table columns which is used when there is not enough space for 1210 * all visible columns.<p> 1211 * 1212 * @param prop the table property 1213 * @return the alternative column width 1214 */ 1215 private int getAlternativeWidthForExpandingColumns(CmsResourceTableProperty prop) { 1216 1217 if (prop.getId().equals(CmsResourceTableProperty.PROPERTY_RESOURCE_NAME.getId())) { 1218 return 200; 1219 } 1220 if (prop.getId().equals(CmsResourceTableProperty.PROPERTY_TITLE.getId())) { 1221 return 300; 1222 } 1223 if (prop.getId().equals(CmsResourceTableProperty.PROPERTY_NAVIGATION_TEXT.getId())) { 1224 return 200; 1225 } 1226 return 200; 1227 } 1228 1229 /** 1230 * Updates the given item in the file table.<p> 1231 * 1232 * @param itemId the item id 1233 * @param remove true if the item should be removed only 1234 */ 1235 private void updateItem(CmsUUID itemId, boolean remove) { 1236 1237 if (remove) { 1238 String idStr = itemId != null ? itemId.toString() : null; 1239 m_container.removeItem(idStr); 1240 return; 1241 } 1242 1243 CmsObject cms = A_CmsUI.getCmsObject(); 1244 try { 1245 CmsResource resource = cms.readResource(itemId, CmsResourceFilter.ALL); 1246 fillItem(cms, resource, OpenCms.getWorkplaceManager().getWorkplaceLocale(cms)); 1247 1248 } catch (CmsVfsResourceNotFoundException e) { 1249 if (null != itemId) { 1250 m_container.removeItem(itemId.toString()); 1251 } 1252 LOG.debug("Failed to update file table item, removing it from view.", e); 1253 } catch (CmsException e) { 1254 LOG.error(e.getLocalizedMessage(), e); 1255 } 1256 } 1257 1258}