001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (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.workplace.comparison; 029 030import com.alkacon.diff.Diff; 031 032import org.opencms.jsp.CmsJspActionElement; 033import org.opencms.util.CmsStringUtil; 034import org.opencms.workplace.CmsDialog; 035import org.opencms.workplace.CmsWorkplace; 036import org.opencms.workplace.CmsWorkplaceSettings; 037import org.opencms.workplace.list.A_CmsListDialog; 038import org.opencms.workplace.tools.A_CmsHtmlIconButton; 039import org.opencms.workplace.tools.CmsHtmlIconButtonStyleEnum; 040 041import java.io.BufferedReader; 042import java.io.IOException; 043import java.io.StringReader; 044 045import jakarta.servlet.http.HttpServletRequest; 046import jakarta.servlet.jsp.JspException; 047import jakarta.servlet.jsp.JspWriter; 048 049/** 050 * Provides a GUI for the configuration file comparison dialog.<p> 051 * 052 * @since 6.0.0 053 */ 054public abstract class A_CmsDiffViewDialog extends CmsDialog { 055 056 /** Diff mode. */ 057 private CmsDiffViewMode m_mode; 058 059 /** 060 * Default constructor.<p> 061 * 062 * @param jsp an initialized JSP action element 063 */ 064 protected A_CmsDiffViewDialog(CmsJspActionElement jsp) { 065 066 super(jsp); 067 setParamStyle(STYLE_NEW); 068 } 069 070 /** 071 * Returns the html code for a deactivated empfasized button.<p> 072 * 073 * @param name the label of the button 074 * @param iconPath the path to the icon 075 * 076 * @return the html code for a deactivated empfasized button 077 */ 078 public String deactivatedEmphasizedButtonHtml(String name, String iconPath) { 079 080 StringBuffer result = new StringBuffer(); 081 result.append( 082 "<span style='vertical-align:middle;'><img style='width:20px;height:20px;display:inline;vertical-align:middle;text-decoration:none;' src=\'"); 083 result.append(CmsWorkplace.getSkinUri()); 084 result.append(iconPath); 085 result.append("\' alt=\'"); 086 result.append(name); 087 result.append("\' title=\'"); 088 result.append(name); 089 result.append("\'> <b>"); 090 result.append(name); 091 result.append("</b></span>"); 092 return result.toString(); 093 } 094 095 /** 096 * Performs the dialog actions depending on the initialized action and displays the dialog form.<p> 097 * 098 * @throws Exception if writing to the JSP out fails 099 */ 100 public void displayDialog() throws Exception { 101 102 if (getAction() == ACTION_CANCEL) { 103 actionCloseDialog(); 104 } 105 JspWriter out = getJsp().getJspContext().getOut(); 106 out.print("<link rel='stylesheet' type='text/css' href='"); 107 out.print(getStyleUri(getJsp())); 108 out.println("diff.css'>"); 109 out.println(dialogContentStart(getParamTitle())); 110 out.print("<form name='diff-form' method='post' action='"); 111 out.print(getDialogUri()); 112 out.println("'>"); 113 out.println(allParamsAsHidden()); 114 out.println("</form>"); 115 // icon is displayed on the right in order that the user needs not scroll to the icon for long lines 116 out.println("<p>"); 117 out.println(getDiffOnlyButtonsHtml()); 118 out.println("</p>"); 119 out.println(dialogBlockStart(null)); 120 out.println("<table cellspacing='0' cellpadding='0' class='xmlTable'>\n<tr><td><pre style='overflow:auto'>"); 121 try { 122 CmsHtmlDifferenceConfiguration conf = new CmsHtmlDifferenceConfiguration( 123 getMode() == CmsDiffViewMode.ALL ? -1 : getLinesBeforeSkip(), 124 getLocale()); 125 String diff = Diff.diffAsHtml(getOriginalSource(), getCopySource(), conf); 126 if (CmsStringUtil.isNotEmpty(diff)) { 127 out.println(diff); 128 } else { 129 // print original source, if there are no differences 130 out.println( 131 wrapLinesWithUnchangedStyle( 132 CmsStringUtil.substitute(CmsStringUtil.escapeHtml(getOriginalSource()), "<br/>", ""))); 133 } 134 } catch (Exception e) { 135 out.print(e); 136 } 137 out.println("</pre></td></tr>\n</table>"); 138 out.println(dialogBlockEnd()); 139 out.println(dialogContentEnd()); 140 out.println(dialogEnd()); 141 out.println(bodyEnd()); 142 out.println(htmlEnd()); 143 } 144 145 /** 146 * Returns the mode.<p> 147 * 148 * @return the mode 149 */ 150 public CmsDiffViewMode getMode() { 151 152 return m_mode; 153 } 154 155 /** 156 * Returns the parameter value for the Mode.<p> 157 * 158 * @return the parameter value for the Mode 159 */ 160 public String getParamMode() { 161 162 if (m_mode == null) { 163 return null; 164 } 165 return m_mode.getMode(); 166 } 167 168 /** 169 * Returns the html for two buttons, whereby the third parameter determines which one is active.<p> 170 * 171 * @param label1 the label for the first button 172 * @param label2 the label for the second button 173 * @param firstActive a flag indicating wheter the first or second button is active 174 * @param onClick1 the action to be performed if the first button is clicked 175 * @param onClick2 the action to be performed if the second button is clicked 176 * 177 * @return the html for two buttons, whereby the third parameter determines which one is active 178 */ 179 public String getTwoButtonsHtml( 180 String label1, 181 String label2, 182 String onClick1, 183 String onClick2, 184 boolean firstActive) { 185 186 StringBuffer result = new StringBuffer(); 187 if (firstActive) { 188 result.append( 189 A_CmsHtmlIconButton.defaultButtonHtml( 190 CmsHtmlIconButtonStyleEnum.SMALL_ICON_TEXT, 191 "id", 192 label1, 193 null, 194 true, 195 A_CmsListDialog.ICON_DETAILS_SHOW, 196 null, 197 onClick1)); 198 result.append(" "); 199 result.append(deactivatedEmphasizedButtonHtml(label2, A_CmsListDialog.ICON_DETAILS_HIDE)); 200 } else { 201 202 result.append(deactivatedEmphasizedButtonHtml(label1, A_CmsListDialog.ICON_DETAILS_HIDE)); 203 result.append(" "); 204 result.append( 205 A_CmsHtmlIconButton.defaultButtonHtml( 206 CmsHtmlIconButtonStyleEnum.SMALL_ICON_TEXT, 207 "id", 208 label2, 209 null, 210 true, 211 A_CmsListDialog.ICON_DETAILS_SHOW, 212 null, 213 onClick2)); 214 } 215 result.append(" "); 216 return result.toString(); 217 } 218 219 /** 220 * Sets the mode.<p> 221 * 222 * @param mode the mode to set 223 */ 224 public void setMode(CmsDiffViewMode mode) { 225 226 m_mode = mode; 227 } 228 229 /** 230 * Sets the parameter value for the Mode.<p> 231 * 232 * @param mode the parameter value for the Mode to set 233 */ 234 public void setParamMode(String mode) { 235 236 m_mode = CmsDiffViewMode.valueOf(mode); 237 } 238 239 /** 240 * Returns the text to compare as copy.<p> 241 * 242 * @return the text to compare as copy 243 */ 244 protected abstract String getCopySource(); 245 246 /** 247 * Returns the number of lines to show before they are skipped.<p> 248 * 249 * @return the number of lines to show before they are skipped 250 */ 251 protected abstract int getLinesBeforeSkip(); 252 253 /** 254 * Returns the text to compare as original.<p> 255 * 256 * @return the text to compare as original 257 */ 258 protected abstract String getOriginalSource(); 259 260 /** 261 * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, jakarta.servlet.http.HttpServletRequest) 262 */ 263 @Override 264 protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) { 265 266 super.initWorkplaceRequestValues(settings, request); 267 if (CmsStringUtil.isEmptyOrWhitespaceOnly(getParamMode())) { 268 // ensure a valid mode is set 269 m_mode = CmsDiffViewMode.DIFF_ONLY; 270 } 271 // test the needed parameters 272 try { 273 validateParamaters(); 274 } catch (Exception e) { 275 // close if parameters not available 276 setAction(ACTION_CANCEL); 277 try { 278 actionCloseDialog(); 279 } catch (JspException e1) { 280 // noop 281 } 282 return; 283 } 284 } 285 286 /** 287 * Validates the parameters.<p> 288 * 289 * @throws Exception if something goes wrong 290 */ 291 protected abstract void validateParamaters() throws Exception; 292 293 /** 294 * 295 * Returns a diff text wrapped with formatting style.<p> 296 * 297 * @param diff the text to wrap with CSS formatting 298 * @return the text with formatting styles wrapped 299 * @throws IOException if something goes wrong 300 */ 301 protected String wrapLinesWithUnchangedStyle(String diff) throws IOException { 302 303 String line; 304 StringBuffer result = new StringBuffer(); 305 BufferedReader br = new BufferedReader(new StringReader(diff)); 306 while ((line = br.readLine()) != null) { 307 if ("".equals(line.trim())) { 308 line = " "; 309 } 310 result.append("<div class=\"df-unc\"><span class=\"df-unc\">").append(line).append("</span></div>\n"); 311 } 312 return result.toString(); 313 } 314 315 /** 316 * Returns the html code for the buttons 'show only differences' and 'show everything'.<p> 317 * 318 * @return the html code for the buttons 'show only differences' and 'show everything' 319 */ 320 String getDiffOnlyButtonsHtml() { 321 322 StringBuffer result = new StringBuffer(); 323 if (!getOriginalSource().equals(getCopySource())) { 324 String onClick1 = "javascript:document.forms['diff-form'].mode.value = '"; 325 String onClick2 = "javascript:document.forms['diff-form'].mode.value = '"; 326 onClick1 += CmsDiffViewMode.ALL; 327 onClick2 += CmsDiffViewMode.DIFF_ONLY; 328 onClick1 += "'; document.forms['diff-form'].submit();"; 329 onClick2 += "'; document.forms['diff-form'].submit();"; 330 result.append( 331 getTwoButtonsHtml( 332 CmsDiffViewMode.DIFF_ONLY.getName().key(getLocale()), 333 CmsDiffViewMode.ALL.getName().key(getLocale()), 334 onClick1, 335 onClick2, 336 getMode() == CmsDiffViewMode.DIFF_ONLY)); 337 } else { 338 // display all text, if there are no differences 339 setMode(CmsDiffViewMode.ALL); 340 } 341 return result.toString(); 342 } 343 344}