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 GmbH & Co. KG, 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.workplace.comparison; 029 030import org.opencms.file.CmsFile; 031import org.opencms.file.CmsObject; 032import org.opencms.jsp.CmsJspActionElement; 033import org.opencms.main.CmsException; 034import org.opencms.main.CmsLog; 035import org.opencms.util.CmsDateUtil; 036import org.opencms.util.CmsStringUtil; 037import org.opencms.util.CmsUUID; 038import org.opencms.workplace.commons.CmsHistoryList; 039import org.opencms.workplace.list.A_CmsListDialog; 040import org.opencms.workplace.list.CmsListColumnAlignEnum; 041import org.opencms.workplace.list.CmsListColumnDefinition; 042import org.opencms.workplace.list.CmsListDefaultAction; 043import org.opencms.workplace.list.CmsListDirectAction; 044import org.opencms.workplace.list.CmsListIndependentAction; 045import org.opencms.workplace.list.CmsListItem; 046import org.opencms.workplace.list.CmsListItemDetails; 047import org.opencms.workplace.list.CmsListMetadata; 048import org.opencms.workplace.list.CmsListOrderEnum; 049import org.opencms.xml.types.CmsXmlDateTimeValue; 050 051import java.io.IOException; 052import java.text.DateFormat; 053import java.util.ArrayList; 054import java.util.Date; 055import java.util.HashMap; 056import java.util.Iterator; 057import java.util.List; 058import java.util.Map; 059 060import javax.servlet.ServletException; 061import javax.servlet.http.HttpServletRequest; 062import javax.servlet.http.HttpServletResponse; 063import javax.servlet.jsp.PageContext; 064 065import org.apache.commons.logging.Log; 066 067/** 068 * Element comparison list view. <p> 069 * 070 * @since 6.0.0 071 */ 072public class CmsElementComparisonList extends A_CmsListDialog { 073 074 /** list action id constant. */ 075 public static final String LIST_ACTION_ICON = "ai"; 076 077 /** list action id constant. */ 078 public static final String LIST_ACTION_STATUS = "at"; 079 080 /** list column id constant. */ 081 public static final String LIST_COLUMN_ATTRIBUTE = "ca"; 082 083 /** list column id constant. */ 084 public static final String LIST_COLUMN_ICON = "ci"; 085 086 /** list column id constant. */ 087 public static final String LIST_COLUMN_LOCALE = "cl"; 088 089 /** list column id constant. */ 090 public static final String LIST_COLUMN_STATUS = "cs"; 091 092 /** list column id constant. */ 093 public static final String LIST_COLUMN_TYPE = "cy"; 094 095 /** list column id constant. */ 096 public static final String LIST_COLUMN_VERSION_1 = "cv"; 097 098 /** list column id constant. */ 099 public static final String LIST_COLUMN_VERSION_2 = "cw"; 100 101 /** list default action id constant. */ 102 public static final String LIST_DEFACTION_VIEW = "dv"; 103 104 /** list independent action id constant. */ 105 public static final String LIST_DETAIL_TYPE = "dt"; 106 107 /** list independent action id constant. */ 108 public static final String LIST_IACTION_COMPARE_ALL = "ava"; 109 110 /** list independent action id constant. */ 111 public static final String LIST_IACTION_SHOW = "isy"; 112 113 /** List id constant. */ 114 public static final String LIST_ID = "hiecl"; 115 116 /** Request parameter name for the element. */ 117 public static final String PARAM_ELEMENT = "element"; 118 119 /** Request parameter name for the locale. */ 120 public static final String PARAM_LOCALE = "locale"; 121 122 /** The log object for this class. */ 123 private static final Log LOG = CmsLog.getLog(CmsElementComparisonList.class); 124 125 /** Parameter value for the structure id of the first file. */ 126 private String m_paramId1; 127 128 /** Parameter value for the structure id of the second file. */ 129 private String m_paramId2; 130 131 /** Parameter value for the version of the first file. */ 132 private String m_paramVersion1; 133 134 /** Parameter value for the version of the second file. */ 135 private String m_paramVersion2; 136 137 /** flag indicating whether xml contents are compared.<p> */ 138 private boolean m_xmlContentComparisonMode; 139 140 /** 141 * Public constructor.<p> 142 * 143 * @param jsp an initialized JSP action element 144 */ 145 public CmsElementComparisonList(CmsJspActionElement jsp) { 146 147 this(LIST_ID, jsp); 148 } 149 150 /** 151 * Public constructor with JSP variables.<p> 152 * 153 * @param context the JSP page context 154 * @param req the JSP request 155 * @param res the JSP response 156 */ 157 public CmsElementComparisonList(PageContext context, HttpServletRequest req, HttpServletResponse res) { 158 159 this(new CmsJspActionElement(context, req, res)); 160 } 161 162 /** 163 * Protected constructor.<p> 164 * 165 * @param listId the id of the specialized list 166 * @param jsp an initialized JSP action element 167 */ 168 protected CmsElementComparisonList(String listId, CmsJspActionElement jsp) { 169 170 super( 171 jsp, 172 listId, 173 Messages.get().container(Messages.GUI_COMPARE_CONTENT_0), 174 LIST_COLUMN_LOCALE, 175 CmsListOrderEnum.ORDER_ASCENDING, 176 null); 177 } 178 179 public static String formatContentValueForDiffTable( 180 CmsObject cms, 181 CmsElementComparison comparison, 182 String origValue) { 183 184 String result = CmsStringUtil.escapeHtml( 185 CmsStringUtil.substitute( 186 CmsStringUtil.trimToSize(origValue, CmsPropertyComparisonList.TRIM_AT_LENGTH), 187 "\n", 188 "")); 189 190 // formatting DateTime 191 if (comparison instanceof CmsXmlContentElementComparison) { 192 if (((CmsXmlContentElementComparison)comparison).getType().equals(CmsXmlDateTimeValue.TYPE_NAME)) { 193 if (CmsStringUtil.isNotEmpty(result)) { 194 195 result = CmsDateUtil.getDateTime( 196 new Date(Long.parseLong(result)), 197 DateFormat.SHORT, 198 cms.getRequestContext().getLocale()); 199 } 200 } 201 } 202 return result; 203 } 204 205 /** 206 * 207 * @see org.opencms.workplace.list.A_CmsListDialog#executeListIndepActions() 208 */ 209 @Override 210 public void executeListIndepActions() { 211 212 if (getParamListAction().equals(LIST_IACTION_COMPARE_ALL)) { 213 // called if all elements are to be compared 214 Map<String, String[]> params = new HashMap<String, String[]>(); 215 params.put(CmsHistoryList.PARAM_VERSION_1, new String[] {getParamVersion1()}); 216 params.put(CmsHistoryList.PARAM_VERSION_2, new String[] {getParamVersion2()}); 217 params.put(CmsHistoryList.PARAM_ID_1, new String[] {getParamId1()}); 218 params.put(CmsHistoryList.PARAM_ID_2, new String[] {getParamId2()}); 219 params.put( 220 CmsPropertyComparisonList.PARAM_COMPARE, 221 new String[] {CmsResourceComparisonDialog.COMPARE_ALL_ELEMENTS}); 222 params.put(PARAM_RESOURCE, new String[] {getParamResource()}); 223 // forward to the element difference screen 224 try { 225 getToolManager().jspForwardTool(this, "/history/comparison/difference", params); 226 } catch (Exception e) { 227 LOG.debug(e.getMessage(), e); 228 } 229 230 } 231 super.executeListIndepActions(); 232 } 233 234 /** 235 * @see org.opencms.workplace.list.A_CmsListDialog#executeListMultiActions() 236 */ 237 @Override 238 public void executeListMultiActions() { 239 240 throwListUnsupportedActionException(); 241 } 242 243 /** 244 * @see org.opencms.workplace.list.A_CmsListDialog#executeListSingleActions() 245 */ 246 @Override 247 public void executeListSingleActions() throws IOException, ServletException { 248 249 Map<String, String[]> params = new HashMap<String, String[]>(); 250 params.put(CmsHistoryList.PARAM_VERSION_1, new String[] {getParamVersion1()}); 251 params.put(CmsHistoryList.PARAM_VERSION_2, new String[] {getParamVersion2()}); 252 params.put(CmsHistoryList.PARAM_ID_1, new String[] {getParamId1()}); 253 params.put(CmsHistoryList.PARAM_ID_2, new String[] {getParamId2()}); 254 params.put(PARAM_LOCALE, new String[] {getSelectedItem().get(LIST_COLUMN_LOCALE).toString()}); 255 params.put(PARAM_ELEMENT, new String[] {getSelectedItem().get(LIST_COLUMN_ATTRIBUTE).toString()}); 256 params.put(PARAM_RESOURCE, new String[] {getParamResource()}); 257 // forward to the element difference screen 258 getToolManager().jspForwardTool(this, "/history/comparison/difference", params); 259 260 } 261 262 /** 263 * Returns the paramId1.<p> 264 * 265 * @return the paramId1 266 */ 267 public String getParamId1() { 268 269 return m_paramId1; 270 } 271 272 /** 273 * Returns the paramId2.<p> 274 * 275 * @return the paramId2 276 */ 277 public String getParamId2() { 278 279 return m_paramId2; 280 } 281 282 /** 283 * Returns the paramNewversionid.<p> 284 * 285 * @return the paramNewversionid 286 */ 287 public String getParamVersion1() { 288 289 return m_paramVersion1; 290 } 291 292 /** 293 * Returns the paramOldversionid.<p> 294 * 295 * @return the paramOldversionid 296 */ 297 public String getParamVersion2() { 298 299 return m_paramVersion2; 300 } 301 302 /** 303 * Sets the paramId1.<p> 304 * 305 * @param paramId1 the paramId1 to set 306 */ 307 public void setParamId1(String paramId1) { 308 309 m_paramId1 = paramId1; 310 } 311 312 /** 313 * Sets the paramId2.<p> 314 * 315 * @param paramId2 the paramId2 to set 316 */ 317 public void setParamId2(String paramId2) { 318 319 m_paramId2 = paramId2; 320 } 321 322 /** 323 * Sets the paramNewversionid.<p> 324 * 325 * @param paramNewversionid the paramNewversionid to set 326 */ 327 public void setParamVersion1(String paramNewversionid) { 328 329 m_paramVersion1 = paramNewversionid; 330 } 331 332 /** 333 * Sets the paramOldversionid.<p> 334 * 335 * @param paramOldversionid the paramOldversionid to set 336 */ 337 public void setParamVersion2(String paramOldversionid) { 338 339 m_paramVersion2 = paramOldversionid; 340 } 341 342 /** 343 * @see org.opencms.workplace.list.A_CmsListDialog#fillDetails(java.lang.String) 344 */ 345 @Override 346 protected void fillDetails(String detailId) { 347 348 // no-op 349 } 350 351 /** 352 * @see org.opencms.workplace.list.A_CmsListDialog#getListItems() 353 */ 354 @Override 355 protected List<CmsListItem> getListItems() throws CmsException { 356 357 List<CmsListItem> result = new ArrayList<CmsListItem>(); 358 CmsFile resource1 = CmsResourceComparisonDialog.readFile( 359 getCms(), 360 new CmsUUID(getParamId1()), 361 getParamVersion1()); 362 CmsFile resource2 = CmsResourceComparisonDialog.readFile( 363 getCms(), 364 new CmsUUID(getParamId2()), 365 getParamVersion2()); 366 Iterator<CmsElementComparison> diffs = new CmsXmlDocumentComparison( 367 getCms(), 368 resource1, 369 resource2).getElements().iterator(); 370 while (diffs.hasNext()) { 371 CmsElementComparison comparison = diffs.next(); 372 String locale = comparison.getLocale().toString(); 373 String attribute = comparison.getName(); 374 CmsListItem item = getList().newItem(locale + attribute); 375 item.set(LIST_COLUMN_LOCALE, locale); 376 item.set(LIST_COLUMN_ATTRIBUTE, attribute); 377 if (comparison instanceof CmsXmlContentElementComparison) { 378 m_xmlContentComparisonMode = true; 379 item.set(LIST_COLUMN_TYPE, ((CmsXmlContentElementComparison)comparison).getType()); 380 } 381 if (CmsResourceComparison.TYPE_ADDED.equals(comparison.getStatus())) { 382 item.set(LIST_COLUMN_STATUS, key(Messages.GUI_COMPARE_ADDED_0)); 383 } else if (CmsResourceComparison.TYPE_REMOVED.equals(comparison.getStatus())) { 384 item.set(LIST_COLUMN_STATUS, key(Messages.GUI_COMPARE_REMOVED_0)); 385 } else if (CmsResourceComparison.TYPE_CHANGED.equals(comparison.getStatus())) { 386 item.set(LIST_COLUMN_STATUS, key(Messages.GUI_COMPARE_CHANGED_0)); 387 } else { 388 if (!getList().getMetadata().getItemDetailDefinition(LIST_IACTION_SHOW).isVisible()) { 389 // do not display entry 390 continue; 391 } else { 392 item.set(LIST_COLUMN_STATUS, key(Messages.GUI_COMPARE_UNCHANGED_0)); 393 } 394 } 395 String value1 = CmsStringUtil.escapeHtml( 396 CmsStringUtil.substitute( 397 CmsStringUtil.trimToSize(comparison.getVersion1(), CmsPropertyComparisonList.TRIM_AT_LENGTH), 398 "\n", 399 "")); 400 401 // formatting DateTime 402 if (comparison instanceof CmsXmlContentElementComparison) { 403 if (((CmsXmlContentElementComparison)comparison).getType().equals(CmsXmlDateTimeValue.TYPE_NAME)) { 404 if (CmsStringUtil.isNotEmpty(value1)) { 405 value1 = CmsDateUtil.getDateTime( 406 new Date(Long.parseLong(value1)), 407 DateFormat.SHORT, 408 getCms().getRequestContext().getLocale()); 409 } 410 } 411 } 412 item.set(LIST_COLUMN_VERSION_1, value1); 413 414 String origValue = comparison.getVersion2(); 415 String value2 = formatContentValueForDiffTable(getCms(), comparison, origValue); 416 item.set(LIST_COLUMN_VERSION_2, value2); 417 result.add(item); 418 } 419 420 getList().getMetadata().getColumnDefinition(LIST_COLUMN_VERSION_1).setName( 421 Messages.get().container( 422 Messages.GUI_COMPARE_VERSION_1, 423 CmsHistoryListUtil.getDisplayVersion(getParamVersion1(), getLocale()))); 424 getList().getMetadata().getColumnDefinition(LIST_COLUMN_VERSION_2).setName(Messages.get().container( 425 Messages.GUI_COMPARE_VERSION_1, 426 CmsHistoryListUtil.getDisplayVersion(getParamVersion2(), getLocale()))); 427 return result; 428 } 429 430 /** 431 * @see org.opencms.workplace.list.A_CmsListDialog#setColumns(org.opencms.workplace.list.CmsListMetadata) 432 */ 433 @Override 434 protected void setColumns(CmsListMetadata metadata) { 435 436 // create column for icon 437 CmsListColumnDefinition iconCol = new CmsListColumnDefinition(LIST_COLUMN_ICON); 438 iconCol.setName(Messages.get().container(Messages.GUI_COMPARE_COLS_ICON_0)); 439 iconCol.setWidth("20"); 440 iconCol.setAlign(CmsListColumnAlignEnum.ALIGN_CENTER); 441 iconCol.setSorteable(true); 442 443 // add state error action 444 CmsListDirectAction addedAction = new CmsListDirectAction(CmsResourceComparison.TYPE_ADDED) { 445 446 @Override 447 public boolean isVisible() { 448 449 String type = getItem().get(LIST_COLUMN_STATUS).toString(); 450 return key(Messages.GUI_COMPARE_ADDED_0).equals(type); 451 } 452 }; 453 addedAction.setName(Messages.get().container(Messages.GUI_COMPARE_ELEM_ADDED_0)); 454 addedAction.setIconPath("tools/ex_history/buttons/added.png"); 455 addedAction.setEnabled(true); 456 iconCol.addDirectAction(addedAction); 457 458 // add state error action 459 CmsListDirectAction removedAction = new CmsListDirectAction(CmsResourceComparison.TYPE_REMOVED) { 460 461 @Override 462 public boolean isVisible() { 463 464 String type = getItem().get(LIST_COLUMN_STATUS).toString(); 465 return key(Messages.GUI_COMPARE_REMOVED_0).equals(type); 466 } 467 }; 468 removedAction.setName(Messages.get().container(Messages.GUI_COMPARE_ELEM_REMOVED_0)); 469 removedAction.setIconPath("tools/ex_history/buttons/removed.png"); 470 removedAction.setEnabled(true); 471 iconCol.addDirectAction(removedAction); 472 473 // add state error action 474 CmsListDirectAction changedAction = new CmsListDirectAction(CmsResourceComparison.TYPE_CHANGED) { 475 476 @Override 477 public boolean isVisible() { 478 479 String type = getItem().get(LIST_COLUMN_STATUS).toString(); 480 return key(Messages.GUI_COMPARE_CHANGED_0).equals(type); 481 } 482 }; 483 changedAction.setName(Messages.get().container(Messages.GUI_COMPARE_ELEM_CHANGED_0)); 484 changedAction.setIconPath("tools/ex_history/buttons/changed.png"); 485 changedAction.setEnabled(true); 486 iconCol.addDirectAction(changedAction); 487 488 // add state error action 489 CmsListDirectAction unchangedAction = new CmsListDirectAction(CmsResourceComparison.TYPE_UNCHANGED) { 490 491 @Override 492 public boolean isVisible() { 493 494 String type = getItem().get(LIST_COLUMN_STATUS).toString(); 495 return key(Messages.GUI_COMPARE_UNCHANGED_0).equals(type); 496 } 497 }; 498 unchangedAction.setName(Messages.get().container(Messages.GUI_COMPARE_ELEM_UNCHANGED_0)); 499 unchangedAction.setIconPath("tools/ex_history/buttons/unchanged.png"); 500 unchangedAction.setEnabled(true); 501 iconCol.addDirectAction(unchangedAction); 502 metadata.addColumn(iconCol); 503 iconCol.setPrintable(false); 504 505 // add column for type 506 CmsListColumnDefinition statusCol = new CmsListColumnDefinition(LIST_COLUMN_STATUS); 507 statusCol.setName(Messages.get().container(Messages.GUI_COMPARE_COLS_STATUS_0)); 508 statusCol.setWidth("10%"); 509 510 CmsListDefaultAction statusColAction = new CmsListDefaultAction(LIST_ACTION_STATUS); 511 statusColAction.setName(Messages.get().container(Messages.GUI_COMPARE_COLS_STATUS_0)); 512 statusColAction.setEnabled(true); 513 statusCol.addDefaultAction(statusColAction); 514 metadata.addColumn(statusCol); 515 statusCol.setPrintable(true); 516 517 // add column for locale 518 CmsListColumnDefinition localeCol = new CmsListColumnDefinition(LIST_COLUMN_LOCALE); 519 localeCol.setName(Messages.get().container(Messages.GUI_COMPARE_COLS_LOCALE_0)); 520 localeCol.setWidth("10%"); 521 metadata.addColumn(localeCol); 522 localeCol.setPrintable(true); 523 524 // add column for element name 525 CmsListColumnDefinition attCol = new CmsListColumnDefinition(LIST_COLUMN_ATTRIBUTE); 526 attCol.setName(Messages.get().container(Messages.GUI_COMPARE_COLS_NAME_0)); 527 attCol.setWidth("10%"); 528 metadata.addColumn(attCol); 529 attCol.setPrintable(true); 530 531 CmsListColumnDefinition typeCol = new CmsListColumnDefinition(LIST_COLUMN_TYPE); 532 typeCol.setName(Messages.get().container(Messages.GUI_COMPARE_COLS_TYPE_0)); 533 typeCol.setWidth("10%"); 534 // display column only if xml content is compared 535 typeCol.setVisible(m_xmlContentComparisonMode); 536 metadata.addColumn(typeCol); 537 typeCol.setPrintable(true); 538 539 // add column for first value 540 CmsListColumnDefinition version1Col = new CmsListColumnDefinition(LIST_COLUMN_VERSION_1); 541 version1Col.setName( 542 Messages.get().container( 543 Messages.GUI_COMPARE_VERSION_1, 544 CmsHistoryListUtil.getDisplayVersion(getParamVersion1(), getLocale()))); 545 version1Col.setWidth("35%"); 546 version1Col.setSorteable(false); 547 metadata.addColumn(version1Col); 548 version1Col.setPrintable(true); 549 550 // add column for second value 551 CmsListColumnDefinition version2Col = new CmsListColumnDefinition(LIST_COLUMN_VERSION_2); 552 version2Col.setName( 553 Messages.get().container( 554 Messages.GUI_COMPARE_VERSION_1, 555 CmsHistoryListUtil.getDisplayVersion(getParamVersion2(), getLocale()))); 556 version2Col.setWidth("35%"); 557 version2Col.setSorteable(false); 558 metadata.addColumn(version2Col); 559 version2Col.setPrintable(true); 560 } 561 562 /** 563 * @see org.opencms.workplace.list.A_CmsListDialog#setIndependentActions(org.opencms.workplace.list.CmsListMetadata) 564 */ 565 @Override 566 protected void setIndependentActions(CmsListMetadata metadata) { 567 568 CmsListIndependentAction compare = new CmsListIndependentAction(LIST_IACTION_COMPARE_ALL); 569 compare.setName(Messages.get().container(Messages.GUI_COMPARE_COMPARE_ALL_0)); 570 compare.setIconPath("tools/ex_history/buttons/compare.png"); 571 compare.setEnabled(true); 572 metadata.addIndependentAction(compare); 573 574 // add event details 575 CmsListItemDetails eventDetails = new CmsListItemDetails(LIST_IACTION_SHOW); 576 eventDetails.setVisible(false); 577 eventDetails.setShowActionName(Messages.get().container(Messages.GUI_COMPARE_SHOW_ALL_ELEMENTS_0)); 578 eventDetails.setHideActionName(Messages.get().container(Messages.GUI_COMPARE_HIDE_IDENTICAL_ELEMENTS_0)); 579 metadata.addItemDetails(eventDetails); 580 } 581 582 /** 583 * @see org.opencms.workplace.list.A_CmsListDialog#setMultiActions(org.opencms.workplace.list.CmsListMetadata) 584 */ 585 @Override 586 protected void setMultiActions(CmsListMetadata metadata) { 587 588 // no-op 589 } 590}