001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (C) Alkacon Software (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.ade.sitemap.client.alias; 029 030import org.opencms.ade.sitemap.client.CmsSitemapView; 031import org.opencms.ade.sitemap.shared.rpc.I_CmsSitemapServiceAsync; 032import org.opencms.gwt.client.CmsCoreProvider; 033import org.opencms.gwt.client.rpc.CmsRpcAction; 034import org.opencms.gwt.client.ui.CmsAlertDialog; 035import org.opencms.gwt.client.util.CmsClientStringUtil; 036import org.opencms.gwt.client.util.CmsDomUtil; 037import org.opencms.gwt.shared.alias.CmsAliasEditValidationReply; 038import org.opencms.gwt.shared.alias.CmsAliasEditValidationRequest; 039import org.opencms.gwt.shared.alias.CmsAliasInitialFetchResult; 040import org.opencms.gwt.shared.alias.CmsAliasMode; 041import org.opencms.gwt.shared.alias.CmsAliasSaveValidationRequest; 042import org.opencms.gwt.shared.alias.CmsAliasTableRow; 043import org.opencms.gwt.shared.alias.CmsRewriteAliasTableRow; 044import org.opencms.gwt.shared.alias.CmsRewriteAliasValidationReply; 045import org.opencms.gwt.shared.alias.CmsRewriteAliasValidationRequest; 046import org.opencms.util.CmsUUID; 047 048import java.util.ArrayList; 049import java.util.HashSet; 050import java.util.List; 051import java.util.Set; 052 053/** 054 * This is the controller class for the alias editor which is responsible for reacting to edit operations on the client 055 * by triggering the corresponding validation or save actions on the server.<p> 056 */ 057public class CmsAliasTableController { 058 059 /** The set of ids of deleted rows. */ 060 protected Set<CmsUUID> m_deletedIds = new HashSet<CmsUUID>(); 061 062 /** The view. */ 063 protected CmsAliasView m_view; 064 065 /** The URL from which the list of aliases can be downloaded. */ 066 String m_downloadUrl; 067 068 /** The initial data loaded from the server. */ 069 List<CmsAliasTableRow> m_initialData; 070 071 /** The site root. */ 072 String m_siteRoot; 073 074 /** 075 * Gets the service to use for validating/saving aliases.<p> 076 * 077 * @return the service used for validating/saving aliases 078 */ 079 protected static I_CmsSitemapServiceAsync getService() { 080 081 return CmsSitemapView.getInstance().getController().getService(); 082 } 083 084 /** 085 * Method which should be called when the selection of the rewrite table has been changed.<p> 086 * 087 * @param selectedSet the set of selected rewrite table entries 088 */ 089 public void changeRewriteSelection(Set<CmsRewriteAliasTableRow> selectedSet) { 090 091 boolean selectionEmpty = selectedSet.isEmpty(); 092 m_view.setRewriteDeleteButtonEnabled(!selectionEmpty); 093 094 } 095 096 /** 097 * This method is called when the selection of the alias table changes.<p> 098 * 099 * @param selectedSet the set of selected rows 100 */ 101 public void changeSelection(Set<CmsAliasTableRow> selectedSet) { 102 103 boolean selectionEmpty = selectedSet.isEmpty(); 104 m_view.setDeleteButtonEnabled(!selectionEmpty); 105 } 106 107 /** 108 * This method is called when the user wants to delete rewrites aliases.<p> 109 * 110 * @param rowsToDelete the rows the user wants to delete 111 */ 112 public void deleteRewrites(List<CmsRewriteAliasTableRow> rowsToDelete) { 113 114 List<CmsRewriteAliasTableRow> liveData = m_view.getRewriteData(); 115 liveData.removeAll(rowsToDelete); 116 m_view.getRewriteTable().getSelectionModel().clear(); 117 updateValidationStatus(); 118 } 119 120 /** 121 * This method is called when the user deletes a set of rows.<p> 122 * 123 * @param rowsToDelete the list of rows which should be deleted 124 */ 125 public void deleteRows(List<CmsAliasTableRow> rowsToDelete) { 126 127 List<CmsAliasTableRow> liveData = m_view.getLiveData(); 128 for (CmsAliasTableRow row : liveData) { 129 CmsUUID structureId = row.getStructureId(); 130 if (structureId != null) { 131 m_deletedIds.add(row.getStructureId()); 132 } 133 } 134 // prevent selection model from going out of synch 135 m_view.getTable().getSelectionModel().clear(); 136 liveData.removeAll(rowsToDelete); 137 updateValidationStatus(); 138 } 139 140 /** 141 * Triggers the download of the current aliases.<p> 142 */ 143 public void download() { 144 145 CmsDomUtil.openWindow(m_downloadUrl + "?site=" + m_siteRoot, "_blank", ""); 146 } 147 148 /** 149 * This method is called after the mode of an alias has been edited.<p> 150 * 151 * @param row the edited row 152 * @param mode the new alias mode 153 */ 154 public void editAliasMode(CmsAliasTableRow row, CmsAliasMode mode) { 155 156 row.setMode(mode); 157 row.setEdited(true); 158 } 159 160 /** 161 * This method is called after the alias path of an alias has been edited.<p> 162 * 163 * @param row the edited row 164 * @param path the new alias path 165 */ 166 public void editAliasPath(CmsAliasTableRow row, String path) { 167 168 row.editAliasPath(path); 169 row.setEdited(true); 170 validate(); 171 172 } 173 174 /** 175 * This method is called when the user wants to add a new alias entry.<p> 176 * 177 * @param aliasPath the alias path 178 * @param resourcePath the resource site path 179 * @param mode the alias mode 180 */ 181 public void editNewAlias(String aliasPath, String resourcePath, CmsAliasMode mode) { 182 183 CmsAliasTableRow row = new CmsAliasTableRow(); 184 row.setEdited(true); 185 row.setAliasPath(aliasPath); 186 row.setResourcePath(resourcePath); 187 row.setMode(mode); 188 validateNew(row); 189 } 190 191 /** 192 * This method is called when the user adds a new rewrite alias.<p> 193 * 194 * @param rewriteRegex the rewrite pattern 195 * @param rewriteReplacement the rewrite replacement string 196 * 197 * @param mode the rewrite mode 198 */ 199 public void editNewRewrite(String rewriteRegex, String rewriteReplacement, CmsAliasMode mode) { 200 201 CmsRewriteAliasTableRow row = new CmsRewriteAliasTableRow( 202 new CmsUUID(CmsClientStringUtil.randomUUID()), 203 rewriteRegex, 204 rewriteReplacement, 205 mode); 206 m_view.clearRewriteNew(); 207 m_view.getRewriteData().add(0, row); 208 validateRewrite(); 209 } 210 211 /** 212 * This method is called when the user has edited the resource path of an alias.<p> 213 * 214 * @param row the alias the table row 215 * @param path the new path 216 */ 217 public void editResourcePath(CmsAliasTableRow row, String path) { 218 219 row.setEdited(true); 220 row.editResourcePath(path); 221 validate(); 222 } 223 224 /** 225 * This method is called when the user has edited a rewrite alias.<p> 226 * 227 * @param object the edited rewrite alias 228 */ 229 public void editRewriteAlias(CmsRewriteAliasTableRow object) { 230 231 validateRewrite(); 232 } 233 234 /** 235 * Loads the initial data from the server.<p> 236 * 237 * @param afterLoad the action that should be executed after loading 238 */ 239 public void load(final Runnable afterLoad) { 240 241 CmsRpcAction<CmsAliasInitialFetchResult> action = new CmsRpcAction<CmsAliasInitialFetchResult>() { 242 243 /** 244 * @see org.opencms.gwt.client.rpc.CmsRpcAction#execute() 245 */ 246 @Override 247 public void execute() { 248 249 getService().getAliasTable(this); 250 start(0, true); 251 } 252 253 /** 254 * @see org.opencms.gwt.client.rpc.CmsRpcAction#onResponse(java.lang.Object) 255 */ 256 @Override 257 public void onResponse(CmsAliasInitialFetchResult aliasTable) { 258 259 stop(false); 260 261 String lockOwner = aliasTable.getAliasTableLockOwner(); 262 if (lockOwner != null) { 263 264 String errorMessage = CmsAliasMessages.messageAliasTableLocked(lockOwner); 265 String title = CmsAliasMessages.messageAliasTableLockedTitle(); 266 CmsAlertDialog alert = new CmsAlertDialog(title, errorMessage); 267 alert.center(); 268 } else { 269 270 m_downloadUrl = aliasTable.getDownloadUrl(); 271 m_initialData = aliasTable.getRows(); 272 m_siteRoot = CmsCoreProvider.get().getSiteRoot(); 273 List<CmsAliasTableRow> copiedData = copyData(m_initialData); 274 List<CmsRewriteAliasTableRow> rewriteData = aliasTable.getRewriteAliases(); 275 m_view.setData(copiedData, rewriteData); 276 if (afterLoad != null) { 277 afterLoad.run(); 278 } 279 } 280 } 281 }; 282 action.execute(); 283 } 284 285 /** 286 * This method is called when the user wants to save the aliases.<p> 287 */ 288 public void save() { 289 290 CmsRpcAction<CmsAliasEditValidationReply> action = new CmsRpcAction<CmsAliasEditValidationReply>() { 291 292 @Override 293 public void execute() { 294 295 start(200, false); 296 297 CmsAliasSaveValidationRequest saveRequest = new CmsAliasSaveValidationRequest(); 298 saveRequest.setSiteRoot(m_siteRoot); 299 List<CmsAliasTableRow> rows = m_view.getLiveData(); 300 saveRequest.setEditedData(rows); 301 saveRequest.setRewriteData(m_view.getRewriteData()); 302 saveRequest.getDeletedIds().addAll(m_deletedIds); 303 saveRequest.setOriginalData(m_initialData); 304 getService().saveAliases(saveRequest, this); 305 } 306 307 @Override 308 public void onResponse(CmsAliasEditValidationReply result) { 309 310 stop(false); 311 if (result == null) { 312 m_view.close(); 313 } else if (result.hasErrors()) { 314 m_view.update(result.getChangedRows()); 315 } 316 } 317 }; 318 action.execute(); 319 } 320 321 /** 322 * Sets the alias editor view.<p> 323 * 324 * @param view the view object 325 */ 326 public void setView(CmsAliasView view) { 327 328 m_view = view; 329 } 330 331 /** 332 * Enables or disables the save button of the view depending on whether there are validation errors.<p> 333 */ 334 protected void updateValidationStatus() { 335 336 boolean hasErrors = false; 337 for (CmsAliasTableRow row : m_view.getLiveData()) { 338 hasErrors |= row.hasErrors(); 339 } 340 for (CmsRewriteAliasTableRow row : m_view.getRewriteData()) { 341 hasErrors |= (row.getError() != null); 342 } 343 344 m_view.setSaveButtonEnabled(!hasErrors); 345 if (hasErrors) { 346 m_view.sortByErrors(); 347 } 348 } 349 350 /** 351 * Triggers server-side validatiom of the alias table.<p> 352 */ 353 protected void validate() { 354 355 CmsRpcAction<CmsAliasEditValidationReply> action = new CmsRpcAction<CmsAliasEditValidationReply>() { 356 357 @Override 358 public void execute() { 359 360 CmsAliasEditValidationRequest validationRequest = new CmsAliasEditValidationRequest(); 361 362 List<CmsAliasTableRow> rows = m_view.getLiveData(); 363 validationRequest.setEditedData(rows); 364 validationRequest.setOriginalData(m_initialData); 365 getService().validateAliases(validationRequest, this); 366 } 367 368 @Override 369 public void onResponse(CmsAliasEditValidationReply result) { 370 371 stop(false); 372 List<CmsAliasTableRow> changedRows = result.getChangedRows(); 373 m_view.update(changedRows); 374 updateValidationStatus(); 375 } 376 377 }; 378 action.execute(); 379 } 380 381 /** 382 * Triggers server-side validation of the alias table and of a new entry which should be added to it.<p> 383 * 384 * @param newEntry the new entry 385 */ 386 protected void validateNew(final CmsAliasTableRow newEntry) { 387 388 CmsRpcAction<CmsAliasEditValidationReply> action = new CmsRpcAction<CmsAliasEditValidationReply>() { 389 390 @Override 391 public void execute() { 392 393 start(200, true); 394 CmsAliasEditValidationRequest validationRequest = new CmsAliasEditValidationRequest(); 395 List<CmsAliasTableRow> rows = m_view.getLiveData(); 396 validationRequest.setEditedData(rows); 397 validationRequest.setNewEntry(newEntry); 398 validationRequest.setOriginalData(m_initialData); 399 getService().validateAliases(validationRequest, this); 400 } 401 402 @Override 403 public void onResponse(CmsAliasEditValidationReply result) { 404 405 stop(false); 406 List<CmsAliasTableRow> tableRows = result.getChangedRows(); 407 CmsAliasTableRow validatedNewEntry = result.getValidatedNewEntry(); 408 if (validatedNewEntry.hasErrors()) { 409 m_view.setNewAliasPathError(validatedNewEntry.getAliasError()); 410 m_view.setNewAliasResourceError(validatedNewEntry.getPathError()); 411 } else { 412 m_view.clearNew(); 413 tableRows.add(validatedNewEntry); 414 } 415 m_view.update(tableRows); 416 updateValidationStatus(); 417 } 418 }; 419 action.execute(); 420 } 421 422 /** 423 * Triggers server-side validation for the rewrite aliases.<p> 424 */ 425 protected void validateRewrite() { 426 427 CmsRpcAction<CmsRewriteAliasValidationReply> action = new CmsRpcAction<CmsRewriteAliasValidationReply>() { 428 429 @Override 430 public void execute() { 431 432 start(200, true); 433 List<CmsRewriteAliasTableRow> rowsToValidate = new ArrayList<CmsRewriteAliasTableRow>(); 434 rowsToValidate.addAll(m_view.getRewriteData()); 435 436 CmsRewriteAliasValidationRequest request = new CmsRewriteAliasValidationRequest(rowsToValidate); 437 getService().validateRewriteAliases(request, this); 438 } 439 440 @Override 441 public void onResponse(CmsRewriteAliasValidationReply result) { 442 443 stop(false); 444 m_view.update(result); 445 updateValidationStatus(); 446 } 447 448 }; 449 action.execute(); 450 } 451 452 /** 453 * Copies a list of rows.<p> 454 * 455 * @param data the original data 456 * 457 * @return the copied data 458 */ 459 List<CmsAliasTableRow> copyData(List<CmsAliasTableRow> data) { 460 461 List<CmsAliasTableRow> result = new ArrayList<CmsAliasTableRow>(); 462 for (CmsAliasTableRow row : data) { 463 CmsAliasTableRow copiedRow = row.copy(); 464 result.add(copiedRow); 465 } 466 return result; 467 } 468 469}