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