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.dialogs; 029 030import org.opencms.file.CmsObject; 031import org.opencms.file.CmsResource; 032import org.opencms.file.history.CmsHistoryProject; 033import org.opencms.file.history.I_CmsHistoryResource; 034import org.opencms.file.types.CmsResourceTypeUnknownFile; 035import org.opencms.file.types.CmsResourceTypeUnknownFolder; 036import org.opencms.file.types.I_CmsResourceType; 037import org.opencms.gwt.CmsVfsService; 038import org.opencms.loader.CmsLoaderException; 039import org.opencms.main.CmsException; 040import org.opencms.main.CmsLog; 041import org.opencms.main.OpenCms; 042import org.opencms.ui.CmsVaadinUtils; 043import org.opencms.ui.I_CmsDialogContext; 044import org.opencms.ui.components.CmsBasicDialog; 045import org.opencms.ui.components.CmsOkCancelActionHandler; 046import org.opencms.ui.components.CmsResourceInfo; 047import org.opencms.util.CmsUUID; 048import org.opencms.workplace.explorer.CmsExplorerTypeSettings; 049import org.opencms.workplace.explorer.CmsResourceUtil; 050 051import java.util.ArrayList; 052import java.util.Collections; 053import java.util.Comparator; 054import java.util.List; 055 056import org.apache.commons.logging.Log; 057 058import com.google.common.collect.Lists; 059import com.vaadin.ui.AbstractOrderedLayout; 060import com.vaadin.ui.Alignment; 061import com.vaadin.ui.Button; 062import com.vaadin.ui.Button.ClickEvent; 063import com.vaadin.ui.Button.ClickListener; 064import com.vaadin.v7.data.Property.ValueChangeEvent; 065import com.vaadin.v7.data.Property.ValueChangeListener; 066import com.vaadin.v7.data.util.IndexedContainer; 067import com.vaadin.v7.ui.CheckBox; 068import com.vaadin.v7.ui.HorizontalLayout; 069import com.vaadin.v7.ui.Label; 070 071/** 072 * Dialog for restoring deleted resources in a folder.<p> 073 */ 074public class CmsRestoreDeletedDialog extends CmsBasicDialog { 075 076 /** Logger instance for this class. */ 077 private static final Log LOG = CmsLog.getLog(CmsRestoreDeletedDialog.class); 078 079 /** Property for storing selection status. */ 080 private static final String PROP_SELECTED = "selected"; 081 082 /** Serial version id. */ 083 private static final long serialVersionUID = 1L; 084 085 /** The cancel button. */ 086 private Button m_cancelButton; 087 088 /** The box containing the widgets representing the deleted resources. */ 089 private AbstractOrderedLayout m_deletedResourceContainer; 090 091 /** The dialog context. */ 092 private I_CmsDialogContext m_dialogContext; 093 094 /** Checkbox for including subfolders. */ 095 private CheckBox m_includeSubfoldersField; 096 097 /** The OK button. */ 098 private Button m_okButton; 099 100 /** Check box to select all resources. */ 101 private CheckBox m_selectAllField; 102 103 /** Data model for check boxes / selection. */ 104 private IndexedContainer m_selectionContainer; 105 106 /** 107 * Creates a new instance.<p> 108 * 109 * @param context the dialog context 110 * @throws CmsException if something goes wrong 111 */ 112 public CmsRestoreDeletedDialog(I_CmsDialogContext context) 113 throws CmsException { 114 115 m_dialogContext = context; 116 CmsVaadinUtils.readAndLocalizeDesign(this, CmsVaadinUtils.getWpMessagesForCurrentLocale(), null); 117 CmsObject cms = context.getCms(); 118 List<I_CmsHistoryResource> deletedResources = readDeletedResources( 119 m_includeSubfoldersField.getValue().booleanValue()); 120 initDeletedResources(cms, deletedResources); 121 m_cancelButton.addClickListener(new ClickListener() { 122 123 private static final long serialVersionUID = 1L; 124 125 public void buttonClick(ClickEvent event) { 126 127 cancel(); 128 } 129 }); 130 131 m_includeSubfoldersField.addValueChangeListener(new ValueChangeListener() { 132 133 private static final long serialVersionUID = 1L; 134 135 public void valueChange(ValueChangeEvent event) { 136 137 onSubFolderChange((Boolean)event.getProperty().getValue()); 138 } 139 }); 140 141 m_selectAllField.addValueChangeListener(new ValueChangeListener() { 142 143 private static final long serialVersionUID = 1L; 144 145 public void valueChange(ValueChangeEvent event) { 146 147 onSelectAllChange((Boolean)(event.getProperty().getValue())); 148 } 149 }); 150 m_okButton.addClickListener(new ClickListener() { 151 152 private static final long serialVersionUID = 1L; 153 154 public void buttonClick(ClickEvent event) { 155 156 submit(); 157 } 158 }); 159 160 setActionHandler(new CmsOkCancelActionHandler() { 161 162 private static final long serialVersionUID = 1L; 163 164 @Override 165 protected void cancel() { 166 167 CmsRestoreDeletedDialog.this.cancel(); 168 } 169 170 @Override 171 protected void ok() { 172 173 submit(); 174 } 175 }); 176 } 177 178 /** 179 * Gets the ids of the selected resources.<p> 180 * 181 * @return the ids of the selected resources 182 */ 183 public List<CmsUUID> getSelectedIds() { 184 185 List<?> itemIds = m_selectionContainer.getItemIds(); 186 List<CmsUUID> result = Lists.newArrayList(); 187 for (Object itemId : itemIds) { 188 CmsUUID structureId = (CmsUUID)itemId; 189 Boolean value = (Boolean)(m_selectionContainer.getItem(itemId).getItemProperty(PROP_SELECTED).getValue()); 190 if (value.booleanValue()) { 191 result.add(structureId); 192 } 193 } 194 return result; 195 } 196 197 /** 198 * Cancels the dialog.<p> 199 */ 200 void cancel() { 201 202 m_dialogContext.finish(new ArrayList<CmsUUID>()); 203 } 204 205 /** 206 * Called on select all change.<p> 207 * 208 * @param value the new value 209 */ 210 void onSelectAllChange(Boolean value) { 211 212 for (Object id : m_selectionContainer.getItemIds()) { 213 m_selectionContainer.getItem(id).getItemProperty(PROP_SELECTED).setValue(value); 214 } 215 } 216 217 /** 218 * Called on include sub folders change.<p> 219 * 220 * @param value the new value 221 */ 222 void onSubFolderChange(Boolean value) { 223 224 List<I_CmsHistoryResource> historyResources; 225 try { 226 CmsObject cms = m_dialogContext.getCms(); 227 historyResources = readDeletedResources(value.booleanValue()); 228 initDeletedResources(cms, historyResources); 229 } catch (CmsException e) { 230 m_dialogContext.error(e); 231 } 232 } 233 234 /** 235 * Submits the dialog.<p> 236 */ 237 void submit() { 238 239 List<CmsUUID> selectedIds = getSelectedIds(); 240 List<CmsUUID> updated = Lists.newArrayList(); 241 CmsObject cms = m_dialogContext.getCms(); 242 try { 243 for (CmsUUID selectedId : selectedIds) { 244 cms.restoreDeletedResource(selectedId); 245 updated.add(selectedId); 246 } 247 m_dialogContext.finish(updated); 248 } catch (CmsException e) { 249 m_dialogContext.error(e); 250 } 251 } 252 253 /** 254 * Fills the list of resources to select from.<p> 255 * 256 * @param cms the cms context 257 * @param deletedResources the deleted resources 258 * 259 * @throws CmsException if something goes wrong 260 */ 261 private void initDeletedResources(CmsObject cms, List<I_CmsHistoryResource> deletedResources) throws CmsException { 262 263 Collections.sort(deletedResources, new Comparator<I_CmsHistoryResource>() { 264 265 public int compare(I_CmsHistoryResource first, I_CmsHistoryResource second) { 266 267 return first.getRootPath().compareTo(second.getRootPath()); 268 } 269 }); 270 m_deletedResourceContainer.removeAllComponents(); 271 m_selectionContainer = new IndexedContainer(); 272 m_selectionContainer.addContainerProperty(PROP_SELECTED, Boolean.class, Boolean.FALSE); 273 m_okButton.setEnabled(!deletedResources.isEmpty()); 274 if (deletedResources.isEmpty()) { 275 m_deletedResourceContainer.addComponent( 276 new Label(CmsVaadinUtils.getMessageText(org.opencms.workplace.list.Messages.GUI_LIST_EMPTY_0))); 277 278 } 279 for (I_CmsHistoryResource deleted : deletedResources) { 280 CmsExplorerTypeSettings explorerType; 281 try { 282 I_CmsResourceType resType = OpenCms.getResourceManager().getResourceType(deleted.getTypeId()); 283 String typeName = resType.getTypeName(); 284 explorerType = OpenCms.getWorkplaceManager().getExplorerTypeSetting(typeName); 285 } catch (CmsLoaderException e) { 286 explorerType = OpenCms.getWorkplaceManager().getExplorerTypeSetting( 287 deleted.isFile() 288 ? CmsResourceTypeUnknownFile.getStaticTypeName() 289 : CmsResourceTypeUnknownFolder.getStaticTypeName()); 290 } 291 String title = cms.getRequestContext().removeSiteRoot(deleted.getRootPath()); 292 293 long deletionDate = 0; 294 try { 295 CmsHistoryProject hp = cms.readHistoryProject(deleted.getPublishTag()); 296 if (hp != null) { 297 deletionDate = hp.getPublishingDate(); 298 } 299 } catch (CmsException e) { 300 LOG.debug( 301 "Failed to retrieve deletion date for deleted resource " 302 + deleted.getRootPath() 303 + ". Last modification date will be shown."); 304 } 305 String subtitle = CmsVaadinUtils.getMessageText( 306 org.opencms.ui.Messages.GUI_RESTOREDELETED_DATE_VERSION_2, 307 CmsVfsService.formatDateTime(cms, deletionDate == 0 ? deleted.getDateLastModified() : deletionDate), 308 "" + deleted.getVersion()); 309 if (explorerType == null) { 310 explorerType = OpenCms.getWorkplaceManager().getExplorerTypeSetting( 311 deleted.isFile() 312 ? CmsResourceTypeUnknownFile.RESOURCE_TYPE_NAME 313 : CmsResourceTypeUnknownFolder.RESOURCE_TYPE_NAME); 314 } 315 CmsResourceInfo info = new CmsResourceInfo( 316 title, 317 subtitle, 318 CmsResourceUtil.getBigIconResource(explorerType, deleted.getName())); 319 info.setWidth("100%"); 320 HorizontalLayout hl = new HorizontalLayout(); 321 hl.setWidth("100%"); 322 CheckBox checkbox = new CheckBox(); 323 hl.addComponent(checkbox); 324 hl.addComponent(info); 325 hl.setExpandRatio(info, 1); 326 hl.setComponentAlignment(checkbox, Alignment.MIDDLE_LEFT); 327 m_selectionContainer.addItem(deleted.getStructureId()); 328 checkbox.setPropertyDataSource( 329 m_selectionContainer.getItem(deleted.getStructureId()).getItemProperty(PROP_SELECTED)); 330 m_deletedResourceContainer.addComponent(hl); 331 } 332 } 333 334 /** 335 * Reads the deleted resources in the folders selected for the dialog. 336 * 337 * @param includeSubFolders true if deleted resources in subfolders should be included 338 * @return the list of deleted resources 339 * 340 * @throws CmsException if something goes wrong 341 */ 342 private List<I_CmsHistoryResource> readDeletedResources(boolean includeSubFolders) throws CmsException { 343 344 CmsObject cms = m_dialogContext.getCms(); 345 List<I_CmsHistoryResource> result = new ArrayList<>(); 346 for (CmsResource res : m_dialogContext.getResources()) { 347 result.addAll(cms.readDeletedResources(cms.getSitePath(res), includeSubFolders)); 348 } 349 return result; 350 } 351 352}