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.history.diff; 029 030import com.alkacon.diff.Diff; 031 032import org.opencms.main.CmsLog; 033import org.opencms.ui.A_CmsUI; 034import org.opencms.ui.CmsVaadinUtils; 035import org.opencms.util.CmsHtml2TextConverter; 036import org.opencms.util.CmsStringUtil; 037import org.opencms.workplace.comparison.CmsDiffViewMode; 038import org.opencms.workplace.comparison.CmsHtmlDifferenceConfiguration; 039 040import java.io.BufferedReader; 041import java.io.IOException; 042import java.io.StringReader; 043 044import org.apache.commons.logging.Log; 045 046import com.vaadin.v7.data.Property.ValueChangeEvent; 047import com.vaadin.v7.data.Property.ValueChangeListener; 048import com.vaadin.v7.shared.ui.label.ContentMode; 049import com.vaadin.v7.ui.Label; 050import com.vaadin.v7.ui.OptionGroup; 051import com.vaadin.v7.ui.VerticalLayout; 052import com.vaadin.ui.themes.ValoTheme; 053 054/** 055 * Widget used to display a colorized diff view for two texts.<p> 056 */ 057public class CmsTextDiffPanel extends VerticalLayout { 058 059 /** Logger instance for this class. */ 060 private static final Log LOG = CmsLog.getLog(CmsTextDiffPanel.class); 061 062 /** Serial version id. */ 063 private static final long serialVersionUID = 1L; 064 065 /** Label containing the actual diff. */ 066 private Label m_diffHtml; 067 068 /** The current diff mode. */ 069 private String m_diffMode = "diff"; 070 071 /** Selects between different diff modes. */ 072 private OptionGroup m_diffModeSelect; 073 074 /** First text used for comparison. */ 075 private String m_text1; 076 077 /** Second text used for comparison. */ 078 private String m_text2; 079 080 /** The current text mode. */ 081 private String m_textMode = "html"; 082 083 /** Selects between different text modes. */ 084 private OptionGroup m_textOrHtmlSelect; 085 086 /** 087 * Creates a new instance.<p> 088 * 089 * @param text1 the first text 090 * @param text2 the second text 091 * 092 * @param selectTextOrHtml true if the option to select between comparison as text and comparison as HTML should be shown 093 * @param selectDiffMode true if the option to select between showing only the changed lines or all the lines should be displayed 094 */ 095 public CmsTextDiffPanel(String text1, String text2, boolean selectTextOrHtml, boolean selectDiffMode) { 096 CmsVaadinUtils.readAndLocalizeDesign(this, CmsVaadinUtils.getWpMessagesForCurrentLocale(), null); 097 m_text1 = text1; 098 m_text2 = text2; 099 m_textOrHtmlSelect.addStyleName(ValoTheme.OPTIONGROUP_HORIZONTAL); 100 m_textOrHtmlSelect.setValue("html"); 101 m_textOrHtmlSelect.setVisible(selectTextOrHtml); 102 m_diffModeSelect.setValue("diff"); 103 m_diffModeSelect.addStyleName(ValoTheme.OPTIONGROUP_HORIZONTAL); 104 m_diffModeSelect.setVisible(selectDiffMode); 105 106 m_textOrHtmlSelect.addValueChangeListener(new ValueChangeListener() { 107 108 private static final long serialVersionUID = 1L; 109 110 @SuppressWarnings("synthetic-access") 111 public void valueChange(ValueChangeEvent event) { 112 113 m_textMode = event.getProperty().getValue().toString(); 114 update(); 115 } 116 }); 117 118 m_diffModeSelect.addValueChangeListener(new ValueChangeListener() { 119 120 private static final long serialVersionUID = 1L; 121 122 @SuppressWarnings("synthetic-access") 123 public void valueChange(ValueChangeEvent event) { 124 125 m_diffMode = event.getProperty().getValue().toString(); 126 update(); 127 } 128 }); 129 130 update(); 131 } 132 133 /** 134 * Gets the diff HTML based on the selected display options.<p> 135 * 136 * @return the diff HTML to display 137 * 138 * @throws Exception if something goes wrong 139 */ 140 public String getDiffHtml() throws Exception { 141 142 CmsDiffViewMode mode = "all".equals(m_diffMode) ? CmsDiffViewMode.ALL : CmsDiffViewMode.DIFF_ONLY; 143 String text1 = m_text1; 144 String text2 = m_text2; 145 if ("text".equals(m_textMode)) { 146 text1 = CmsHtml2TextConverter.html2text(text1, "UTF-8"); 147 text2 = CmsHtml2TextConverter.html2text(text2, "UTF-8"); 148 } 149 CmsHtmlDifferenceConfiguration conf = new CmsHtmlDifferenceConfiguration( 150 mode == CmsDiffViewMode.ALL ? -1 : 2, 151 A_CmsUI.get().getLocale()); 152 String diff = Diff.diffAsHtml(text1, text2, conf); 153 String html = null; 154 if (CmsStringUtil.isNotEmpty(diff)) { 155 html = diff; 156 } else { 157 html = wrapLinesWithUnchangedStyle( 158 CmsStringUtil.substitute(CmsStringUtil.escapeHtml(m_text1), "<br/>", "")); 159 } 160 return html; 161 162 } 163 164 /** 165 * Updates the displayed diff based on the selected display options.<p> 166 */ 167 public void update() { 168 169 try { 170 String diffHtml = "<pre>" + getDiffHtml() + "</pre>"; 171 m_diffHtml.setContentMode(ContentMode.HTML); 172 m_diffHtml.setValue(diffHtml); 173 } catch (Exception e) { 174 LOG.error(e.getLocalizedMessage(), e); 175 } 176 177 } 178 179 /** 180 * 181 * Returns a diff text wrapped with formatting style.<p> 182 * 183 * @param diff the text to wrap with CSS formatting 184 * @return the text with formatting styles wrapped 185 * @throws IOException if something goes wrong 186 */ 187 protected String wrapLinesWithUnchangedStyle(String diff) throws IOException { 188 189 String line; 190 StringBuffer result = new StringBuffer(); 191 BufferedReader br = new BufferedReader(new StringReader(diff)); 192 while ((line = br.readLine()) != null) { 193 if ("".equals(line.trim())) { 194 line = " "; 195 } 196 result.append("<div class=\"df-unc\"><span class=\"df-unc\">").append(line).append("</span></div>\n"); 197 } 198 return result.toString(); 199 } 200 201}