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.file.CmsProject;
033import org.opencms.file.CmsResource;
034import org.opencms.file.CmsResourceFilter;
035import org.opencms.file.history.CmsHistoryFile;
036import org.opencms.file.history.CmsHistoryResourceHandler;
037import org.opencms.file.types.CmsResourceTypePlain;
038import org.opencms.jsp.CmsJspActionElement;
039import org.opencms.loader.CmsLoaderException;
040import org.opencms.main.CmsException;
041import org.opencms.main.OpenCms;
042import org.opencms.util.CmsStringUtil;
043import org.opencms.util.CmsUUID;
044import org.opencms.workplace.CmsWorkplace;
045import org.opencms.workplace.commons.CmsHistoryList;
046import org.opencms.workplace.list.CmsListIndependentAction;
047import org.opencms.workplace.list.CmsListItem;
048import org.opencms.workplace.list.CmsListItemDetails;
049import org.opencms.workplace.list.CmsListMetadata;
050import org.opencms.workplace.list.CmsListOrderEnum;
051
052import java.io.IOException;
053import java.util.ArrayList;
054import java.util.HashMap;
055import java.util.Iterator;
056import java.util.List;
057import java.util.Map;
058
059import javax.servlet.ServletException;
060import javax.servlet.http.HttpServletRequest;
061import javax.servlet.http.HttpServletResponse;
062import javax.servlet.jsp.PageContext;
063
064/**
065 * List for property comparison including columns for property name and the values. <p>
066 *
067 * @since 6.0.0
068 */
069public class CmsAttributeComparisonList extends CmsPropertyComparisonList {
070
071    /** List id constant. */
072    public static final String AC_LIST_ID = "hiacl";
073
074    /**
075     * Public constructor.<p>
076     *
077     * @param jsp an initialized JSP action element
078     */
079    public CmsAttributeComparisonList(CmsJspActionElement jsp) {
080
081        this(AC_LIST_ID, jsp);
082    }
083
084    /**
085     * Public constructor with JSP variables.<p>
086     *
087     * @param context the JSP page context
088     * @param req the JSP request
089     * @param res the JSP response
090     */
091    public CmsAttributeComparisonList(PageContext context, HttpServletRequest req, HttpServletResponse res) {
092
093        this(new CmsJspActionElement(context, req, res));
094    }
095
096    /**
097     * Protected constructor.<p>
098     *
099     * @param listId the id of the specialized list
100     * @param jsp an initialized JSP action element
101     */
102    protected CmsAttributeComparisonList(String listId, CmsJspActionElement jsp) {
103
104        super(
105            jsp,
106            listId,
107            Messages.get().container(Messages.GUI_COMPARE_ATTRIBUTES_0),
108            LIST_COLUMN_PROPERTY_NAME,
109            CmsListOrderEnum.ORDER_ASCENDING,
110            null);
111    }
112
113    /**
114     * Returns either the historical file or the offline file, depending on the version number.<p>
115     *
116     * @param cms the CmsObject to use
117     * @param structureId the structure id of the file
118     * @param version the historical version number
119     *
120     * @return either the historical file or the offline file, depending on the version number
121     *
122     * @throws CmsException if something goes wrong
123     */
124    protected static CmsFile readFile(CmsObject cms, CmsUUID structureId, String version) throws CmsException {
125
126        if (Integer.parseInt(version) == CmsHistoryResourceHandler.PROJECT_OFFLINE_VERSION) {
127            // offline
128            CmsResource resource = cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
129            return cms.readFile(resource);
130        } else {
131            int ver = Integer.parseInt(version);
132            if (ver < 0) {
133                // online
134                CmsProject project = cms.getRequestContext().getCurrentProject();
135                try {
136                    cms.getRequestContext().setCurrentProject(cms.readProject(CmsProject.ONLINE_PROJECT_ID));
137                    CmsResource resource = cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
138                    return cms.readFile(resource);
139                } finally {
140                    cms.getRequestContext().setCurrentProject(project);
141                }
142            }
143            // backup
144            return cms.readFile((CmsHistoryFile)cms.readResource(structureId, ver));
145        }
146    }
147
148    /**
149     * @see org.opencms.workplace.list.A_CmsListDialog#executeListSingleActions()
150     */
151    @Override
152    public void executeListSingleActions() throws IOException, ServletException {
153
154        // forward to the edit module screen
155        Map<String, String[]> params = new HashMap<String, String[]>();
156        params.put(CmsHistoryList.PARAM_VERSION_1, new String[] {getParamVersion1()});
157        params.put(CmsHistoryList.PARAM_VERSION_2, new String[] {getParamVersion2()});
158        params.put(CmsHistoryList.PARAM_ID_1, new String[] {getParamId1()});
159        params.put(CmsHistoryList.PARAM_ID_2, new String[] {getParamId2()});
160        params.put(PARAM_COMPARE, new String[] {CmsResourceComparisonDialog.COMPARE_ATTRIBUTES});
161        params.put(PARAM_RESOURCE, new String[] {getParamResource()});
162        // forward to the difference screen
163        getToolManager().jspForwardTool(this, "/history/comparison/difference", params);
164    }
165
166    /**
167     * @see org.opencms.workplace.list.A_CmsListDialog#getListItems()
168     */
169    @Override
170    protected List<CmsListItem> getListItems() {
171
172        List<CmsListItem> ret = new ArrayList<CmsListItem>();
173        Iterator<?> diffs = CmsResourceComparison.compareAttributes(
174            getCms(),
175            getResource1(),
176            getResource2()).iterator();
177        while (diffs.hasNext()) {
178            CmsAttributeComparison comparison = (CmsAttributeComparison)diffs.next();
179            CmsListItem item = getList().newItem(comparison.getName());
180            item.set(LIST_COLUMN_PROPERTY_NAME, key(comparison.getName()));
181            item.set(LIST_COLUMN_VERSION_1, CmsStringUtil.trimToSize(comparison.getVersion1(), TRIM_AT_LENGTH));
182            item.set(LIST_COLUMN_VERSION_2, CmsStringUtil.trimToSize(comparison.getVersion2(), TRIM_AT_LENGTH));
183            if (CmsResourceComparison.TYPE_ADDED.equals(comparison.getStatus())) {
184                item.set(LIST_COLUMN_TYPE, key(Messages.GUI_COMPARE_ADDED_0));
185            } else if (CmsResourceComparison.TYPE_REMOVED.equals(comparison.getStatus())) {
186                item.set(LIST_COLUMN_TYPE, key(Messages.GUI_COMPARE_REMOVED_0));
187            } else if (CmsResourceComparison.TYPE_CHANGED.equals(comparison.getStatus())) {
188                item.set(LIST_COLUMN_TYPE, key(Messages.GUI_COMPARE_CHANGED_0));
189            } else {
190                if (!getList().getMetadata().getItemDetailDefinition(LIST_IACTION_SHOW).isVisible()) {
191                    // do not display entry
192                    continue;
193                } else {
194                    item.set(LIST_COLUMN_TYPE, key(Messages.GUI_COMPARE_UNCHANGED_0));
195                }
196            }
197            ret.add(item);
198
199            if (!diffs.hasNext()) {
200                getList().getMetadata().getIndependentAction(LIST_ACTION_VIEW1).setEnabled(getResource1().isFile());
201                getList().getMetadata().getIndependentAction(LIST_ACTION_VIEW2).setEnabled(getResource2().isFile());
202            }
203        }
204        getList().getMetadata().getColumnDefinition(LIST_COLUMN_VERSION_1).setName(
205            Messages.get().container(
206                Messages.GUI_COMPARE_VERSION_1,
207                CmsHistoryListUtil.getDisplayVersion(getParamVersion1(), getLocale())));
208        getList().getMetadata().getColumnDefinition(LIST_COLUMN_VERSION_2).setName(Messages.get().container(
209            Messages.GUI_COMPARE_VERSION_1,
210            CmsHistoryListUtil.getDisplayVersion(getParamVersion2(), getLocale())));
211
212        return ret;
213    }
214
215    /**
216     * Returns the html code to display a file version.<p>
217     *
218     * @param structureId the structure id of the file to be displayed
219     * @param version the version of the file to be displayed
220     *
221     * @return the html code to display a file version
222     */
223    protected String getViewVersionButtonHtml(CmsUUID structureId, String version) {
224
225        // set flag to activate the preview button of the comparison dialog
226        boolean active = true;
227        try {
228            // only show preview, if the resource is a file
229            // or the version has content
230            if (OpenCms.getResourceManager().getResourceType(getResource1().getTypeId()).isFolder()) {
231                active = false;
232            } else {
233                byte[] content = readFile(getCms(), structureId, version).getContents();
234                if (content.length < 1) {
235                    active = false;
236                }
237            }
238        } catch (CmsLoaderException e) {
239            // ignore, buttons will be shown
240
241        } catch (CmsException e) {
242            // do not show the preview button
243            active = false;
244        }
245
246        // return button only if file resource
247        if (active) {
248            String label = Messages.get().container(
249                Messages.GUI_COMPARE_VIEW_VERSION_1,
250                CmsHistoryListUtil.getDisplayVersion(version, getLocale())).key(getLocale());
251            String iconPath = null;
252            try {
253                String typeName = OpenCms.getResourceManager().getResourceType(
254                    getResource1().getTypeId()).getTypeName();
255                iconPath = CmsWorkplace.RES_PATH_FILETYPES
256                    + OpenCms.getWorkplaceManager().getExplorerTypeSetting(typeName).getIcon();
257            } catch (CmsException e) {
258                iconPath = CmsWorkplace.RES_PATH_FILETYPES
259                    + OpenCms.getWorkplaceManager().getExplorerTypeSetting(
260                        CmsResourceTypePlain.getStaticTypeName()).getIcon();
261            }
262            StringBuffer result = new StringBuffer(1024);
263            result.append("<span class='link' onClick=\"");
264            result.append("window.open('");
265            result.append(getJsp().link(CmsHistoryListUtil.getHistoryLink(getCms(), structureId, version)));
266            result.append("','version','scrollbars=yes', 'resizable=yes', 'width=800', 'height=600')\">");
267            result.append("<img style='width: 16px; height: 16px;' src='");
268            result.append(CmsWorkplace.getSkinUri());
269            result.append(iconPath);
270            result.append("' alt='");
271            result.append(label);
272            result.append("' title='");
273            result.append(label);
274            result.append("'>&nbsp;<a href='#'>");
275            result.append(label);
276            result.append("</a></span>");
277
278            return result.toString();
279        }
280        return "";
281    }
282
283    /**
284     * @see org.opencms.workplace.list.A_CmsListDialog#setIndependentActions(org.opencms.workplace.list.CmsListMetadata)
285     */
286    @Override
287    protected void setIndependentActions(CmsListMetadata metadata) {
288
289        // add the view version action
290        CmsListIndependentAction viewVersion1 = new CmsListIndependentAction(LIST_ACTION_VIEW1) {
291
292            /**
293             * @see org.opencms.workplace.tools.I_CmsHtmlIconButton#buttonHtml(org.opencms.workplace.CmsWorkplace)
294             */
295            @Override
296            public String buttonHtml(CmsWorkplace wp) {
297
298                return ((CmsAttributeComparisonList)wp).getViewVersionButtonHtml(
299                    new CmsUUID(((CmsAttributeComparisonList)wp).getParamId1()),
300                    ((CmsAttributeComparisonList)wp).getParamVersion1());
301            }
302        };
303        metadata.addIndependentAction(viewVersion1);
304        // add the view version action
305        CmsListIndependentAction viewVersion2 = new CmsListIndependentAction(LIST_ACTION_VIEW2) {
306
307            /**
308             * @see org.opencms.workplace.tools.I_CmsHtmlIconButton#buttonHtml(org.opencms.workplace.CmsWorkplace)
309             */
310            @Override
311            public String buttonHtml(CmsWorkplace wp) {
312
313                return ((CmsAttributeComparisonList)wp).getViewVersionButtonHtml(
314                    new CmsUUID(((CmsAttributeComparisonList)wp).getParamId2()),
315                    ((CmsAttributeComparisonList)wp).getParamVersion2());
316            }
317        };
318        metadata.addIndependentAction(viewVersion2);
319
320        // add event details
321        CmsListItemDetails eventDetails = new CmsListItemDetails(LIST_IACTION_SHOW);
322        eventDetails.setVisible(false);
323        eventDetails.setShowActionName(Messages.get().container(Messages.GUI_COMPARE_SHOW_ALL_ATTRIBUTES_0));
324        eventDetails.setHideActionName(Messages.get().container(Messages.GUI_COMPARE_HIDE_IDENTICAL_ATTRIBUTES_0));
325        metadata.addItemDetails(eventDetails);
326    }
327}