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