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.commons;
029
030import org.opencms.db.CmsUserSettings;
031import org.opencms.jsp.CmsJspActionElement;
032import org.opencms.main.CmsException;
033import org.opencms.main.OpenCms;
034import org.opencms.relations.CmsRelation;
035import org.opencms.relations.CmsRelationPublishValidator;
036import org.opencms.relations.CmsRelationValidatorInfoEntry;
037import org.opencms.util.CmsStringUtil;
038import org.opencms.workplace.CmsWorkplace;
039import org.opencms.workplace.explorer.CmsResourceUtil;
040import org.opencms.workplace.list.A_CmsListDialog;
041import org.opencms.workplace.list.A_CmsListExplorerDialog;
042import org.opencms.workplace.list.A_CmsListIndependentJsAction;
043import org.opencms.workplace.list.CmsListColumnDefinition;
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.I_CmsListAction;
049import org.opencms.workplace.list.I_CmsListResourceCollector;
050
051import java.util.ArrayList;
052import java.util.Collections;
053import java.util.Iterator;
054import java.util.List;
055
056/**
057 * List for resources with links that could get broken after publishing.<p>
058 *
059 * @since 6.5.5
060 */
061public class CmsPublishBrokenRelationsList extends A_CmsListExplorerDialog {
062
063    /** list action id constant. */
064    public static final String LIST_DETAIL_RELATIONS = "dr";
065
066    /** list action id constant. */
067    public static final String LIST_DETAIL_RELATIONS_PRINT = "drp";
068
069    /** list action id constant. */
070    public static final String LIST_DETAIL_RELATIONS_HIDE = "drh";
071
072    /** list action id constant. */
073    public static final String LIST_DETAIL_RELATIONS_SHOW = "drs";
074
075    /** list id constant. */
076    public static final String LIST_ID = "pbr";
077
078    /** The internal collector instance. */
079    private I_CmsListResourceCollector m_collector;
080
081    /** The broken relations validator object. */
082    private CmsRelationPublishValidator m_validator;
083
084    /**
085     * Public constructor.<p>
086     *
087     * @param jsp an initialized JSP action element
088     * @param relativeTo the 'relative to' path, this only affects the generation of the path for the resource
089     */
090    public CmsPublishBrokenRelationsList(CmsJspActionElement jsp, String relativeTo) {
091
092        super(jsp, LIST_ID, Messages.get().container(Messages.GUI_PUBLISH_BROKENRELATIONS_LIST_NAME_0));
093
094        // prevent paging
095        getList().setMaxItemsPerPage(Integer.MAX_VALUE);
096
097        // set the right resource util parameters
098        CmsResourceUtil resUtil = getResourceUtil();
099        resUtil.setAbbrevLength(50);
100        resUtil.setRelativeTo(getCms().getRequestContext().addSiteRoot(relativeTo));
101        resUtil.setSiteMode(CmsResourceUtil.SITE_MODE_MATCHING);
102    }
103
104    /**
105     * @see org.opencms.workplace.list.A_CmsListDialog#executeListMultiActions()
106     */
107    @Override
108    public void executeListMultiActions() {
109
110        throwListUnsupportedActionException();
111    }
112
113    /**
114     * @see org.opencms.workplace.list.A_CmsListDialog#executeListSingleActions()
115     */
116    @Override
117    public void executeListSingleActions() {
118
119        throwListUnsupportedActionException();
120    }
121
122    /**
123     * @see org.opencms.workplace.list.A_CmsListExplorerDialog#getCollector()
124     */
125    @Override
126    public I_CmsListResourceCollector getCollector() {
127
128        if (m_collector == null) {
129
130            m_validator = new CmsRelationPublishValidator(getCms(), getSettings().getPublishList());
131            List<String> resourceList = new ArrayList<String>(m_validator.keySet());
132            Collections.sort(resourceList);
133
134            m_collector = new CmsPublishBrokenRelationsCollector(this, resourceList);
135        }
136
137        return m_collector;
138    }
139
140    /**
141     * Returns the validator.<p>
142     *
143     * @return the validator
144     */
145    public CmsRelationPublishValidator getValidator() {
146
147        return m_validator;
148    }
149
150    /**
151     * @see org.opencms.workplace.list.A_CmsListDialog#fillDetails(java.lang.String)
152     */
153    @Override
154    protected void fillDetails(String detailId) {
155
156        // get content
157        List<CmsListItem> resourceNames = getList().getAllContent();
158        Iterator<CmsListItem> itResourceNames = resourceNames.iterator();
159        while (itResourceNames.hasNext()) {
160            CmsListItem item = itResourceNames.next();
161            String resourceName = getResourceUtil(item).getResource().getRootPath();
162
163            StringBuffer html = new StringBuffer(128);
164            if (detailId.equals(LIST_DETAIL_RELATIONS)) {
165                // relations
166                CmsRelationValidatorInfoEntry infoEntry = m_validator.getInfoEntry(resourceName);
167                Iterator<CmsRelation> itRelations = infoEntry.getRelations().iterator();
168
169                boolean isDeleted = getResourceUtil(item).getResource().getState().isDeleted();
170                if (isDeleted) {
171                    html.append(CmsPublishBrokenRelationFormatter.PREFIX_SOURCES);
172                } else {
173                    html.append(CmsPublishBrokenRelationFormatter.PREFIX_TARGETS);
174                }
175                // show all links that will get broken
176                while (itRelations.hasNext()) {
177                    CmsRelation relation = itRelations.next();
178                    String relationName;
179                    if (isDeleted) {
180                        relationName = relation.getSourcePath();
181                    } else {
182                        relationName = relation.getTargetPath();
183                    }
184                    if (relationName.startsWith(infoEntry.getSiteRoot())) {
185                        // same site
186                        relationName = relationName.substring(infoEntry.getSiteRoot().length());
187                        relationName = CmsStringUtil.formatResourceName(relationName, 50);
188                    } else {
189                        // other site
190                        String site = OpenCms.getSiteManager().getSiteRoot(relationName);
191                        String siteName = site;
192                        if (site != null) {
193                            relationName = relationName.substring(site.length());
194                            siteName = OpenCms.getSiteManager().getSiteForSiteRoot(site).getTitle();
195                        } else {
196                            siteName = "/";
197                        }
198                        relationName = CmsStringUtil.formatResourceName(relationName, 50);
199                        relationName = key(Messages.GUI_PUBLISH_SITE_RELATION_2, new Object[] {siteName, relationName});
200                    }
201                    html.append(relationName);
202                    html.append("&nbsp;<span style='color: #666666;'>(");
203                    html.append(relation.getType().getLocalizedName(getMessages()));
204                    html.append(")</span>");
205                    if (itRelations.hasNext()) {
206                        html.append("<br>");
207                    }
208                    html.append("\n");
209                }
210            } else {
211                continue;
212            }
213            item.set(detailId, html.toString());
214        }
215    }
216
217    /**
218     * @see org.opencms.workplace.list.A_CmsListExplorerDialog#getListItems()
219     */
220    @Override
221    protected List<CmsListItem> getListItems() throws CmsException {
222
223        String oldSite = getCms().getRequestContext().getSiteRoot();
224        try {
225            getCms().getRequestContext().setSiteRoot("");
226            return super.getListItems();
227        } finally {
228            getCms().getRequestContext().setSiteRoot(oldSite);
229        }
230    }
231
232    /**
233     * @see org.opencms.workplace.list.A_CmsListExplorerDialog#isColumnVisible(int)
234     */
235    @Override
236    protected boolean isColumnVisible(int colFlag) {
237
238        boolean isVisible = (colFlag == CmsUserSettings.FILELIST_TITLE);
239        isVisible = isVisible || (colFlag == LIST_COLUMN_TYPEICON.hashCode());
240        isVisible = isVisible || (colFlag == LIST_COLUMN_LOCKICON.hashCode());
241        isVisible = isVisible || (colFlag == LIST_COLUMN_PROJSTATEICON.hashCode());
242        isVisible = isVisible || (colFlag == LIST_COLUMN_NAME.hashCode());
243        isVisible = isVisible
244            || ((colFlag == LIST_COLUMN_SITE.hashCode()) && (OpenCms.getSiteManager().getSites().size() > 1));
245        return isVisible;
246    }
247
248    /**
249     * @see org.opencms.workplace.list.A_CmsListDialog#setColumns(org.opencms.workplace.list.CmsListMetadata)
250     */
251    @Override
252    protected void setColumns(CmsListMetadata metadata) {
253
254        super.setColumns(metadata);
255
256        Iterator<CmsListColumnDefinition> it = metadata.getColumnDefinitions().iterator();
257        while (it.hasNext()) {
258            CmsListColumnDefinition colDefinition = it.next();
259            colDefinition.setSorteable(false);
260            if (colDefinition.getId().equals(LIST_COLUMN_NAME)) {
261                colDefinition.removeDefaultAction(LIST_DEFACTION_OPEN);
262                colDefinition.setWidth("60%");
263            }
264        }
265    }
266
267    /**
268     * @see org.opencms.workplace.list.A_CmsListDialog#setIndependentActions(org.opencms.workplace.list.CmsListMetadata)
269     */
270    @Override
271    protected void setIndependentActions(CmsListMetadata metadata) {
272
273        /**
274         * Class to render a javascript driven detail action button.<p>
275         */
276        abstract class DetailsJsAction extends A_CmsListIndependentJsAction {
277
278            /**
279             * Default constructor.<p>
280             *
281             * @param id the action id
282             */
283            public DetailsJsAction(String id) {
284
285                super(id);
286            }
287
288            /**
289             * @see org.opencms.workplace.list.CmsListIndependentAction#buttonHtml(org.opencms.workplace.CmsWorkplace)
290             */
291            @Override
292            public String buttonHtml(CmsWorkplace wp) {
293
294                StringBuffer html = new StringBuffer(1024);
295                html.append("\t<span id='");
296                html.append(getId());
297                html.append("' class=\"link");
298                html.append("\"");
299                html.append(" onClick=\"");
300                html.append(resolveOnClic(wp));
301                html.append("\"");
302                html.append(">");
303                html.append("<img src='");
304                html.append(CmsWorkplace.getSkinUri());
305                html.append(getIconPath());
306                html.append("'");
307                html.append(" alt='");
308                html.append(getName().key(wp.getLocale()));
309                html.append("'");
310                html.append(" title='");
311                html.append(getName().key(wp.getLocale()));
312                html.append("'");
313                html.append(">");
314                html.append("&nbsp;");
315                html.append("<a href='#'>");
316                html.append(getName().key(wp.getLocale()));
317                html.append("</a>");
318                html.append("</span>");
319                return html.toString();
320            }
321        }
322
323        I_CmsListAction hideAction = new DetailsJsAction(LIST_DETAIL_RELATIONS_HIDE) {
324
325            /**
326             * @see org.opencms.workplace.list.A_CmsListIndependentJsAction#jsCode(CmsWorkplace)
327             */
328            @Override
329            public String jsCode(CmsWorkplace wp) {
330
331                return "javascript:showBrokenLinks(false);";
332            }
333        };
334        hideAction.setIconPath(A_CmsListDialog.ICON_DETAILS_HIDE);
335        hideAction.setName(Messages.get().container(Messages.GUI_PUBLISH_BROKENRELATIONS_DETAIL_HIDE_RELATIONS_NAME_0));
336        hideAction.setHelpText(
337            Messages.get().container(Messages.GUI_PUBLISH_BROKENRELATIONS_DETAIL_HIDE_RELATIONS_HELP_0));
338        metadata.addIndependentAction(hideAction);
339
340        I_CmsListAction showAction = new DetailsJsAction(LIST_DETAIL_RELATIONS_SHOW) {
341
342            /**
343             * @see org.opencms.workplace.list.A_CmsListIndependentJsAction#jsCode(CmsWorkplace)
344             */
345            @Override
346            public String jsCode(CmsWorkplace wp) {
347
348                return "javascript:showBrokenLinks(true);";
349            }
350        };
351        showAction.setIconPath(A_CmsListDialog.ICON_DETAILS_SHOW);
352        showAction.setName(Messages.get().container(Messages.GUI_PUBLISH_BROKENRELATIONS_DETAIL_SHOW_RELATIONS_NAME_0));
353        showAction.setHelpText(
354            Messages.get().container(Messages.GUI_PUBLISH_BROKENRELATIONS_DETAIL_SHOW_RELATIONS_HELP_0));
355        metadata.addIndependentAction(showAction);
356
357        // create list item detail
358        CmsListItemDetails relationsDetails = new CmsListItemDetails(LIST_DETAIL_RELATIONS) {
359
360            /**
361             * @see org.opencms.workplace.list.CmsListItemDetails#getAction()
362             */
363            @Override
364            public I_CmsListAction getAction() {
365
366                return new CmsListIndependentAction("hide") {
367
368                    /**
369                     * @see org.opencms.workplace.list.CmsListIndependentAction#buttonHtml(org.opencms.workplace.CmsWorkplace)
370                     */
371                    @Override
372                    public String buttonHtml(CmsWorkplace wp) {
373
374                        return "";
375                    }
376                };
377            }
378        };
379        relationsDetails.setAtColumn(LIST_COLUMN_NAME);
380        relationsDetails.setVisible(true);
381        relationsDetails.setPrintable(false);
382        relationsDetails.setFormatter(new CmsPublishBrokenRelationFormatter());
383        relationsDetails.setShowActionName(
384            Messages.get().container(Messages.GUI_PUBLISH_BROKENRELATIONS_DETAIL_SHOW_RELATIONS_NAME_0));
385        relationsDetails.setShowActionHelpText(
386            Messages.get().container(Messages.GUI_PUBLISH_BROKENRELATIONS_DETAIL_SHOW_RELATIONS_HELP_0));
387        relationsDetails.setHideActionName(
388            Messages.get().container(Messages.GUI_PUBLISH_BROKENRELATIONS_DETAIL_HIDE_RELATIONS_NAME_0));
389        relationsDetails.setHideActionHelpText(
390            Messages.get().container(Messages.GUI_PUBLISH_BROKENRELATIONS_DETAIL_HIDE_RELATIONS_HELP_0));
391
392        // add resources info item detail to meta data
393        metadata.addItemDetails(relationsDetails);
394
395        // create list item detail for print view
396        CmsListItemDetails relationsDetailsPrint = new CmsListItemDetails(LIST_DETAIL_RELATIONS_PRINT) {
397
398            /**
399             * @see org.opencms.workplace.list.CmsListItemDetails#getAction()
400             */
401            @Override
402            public I_CmsListAction getAction() {
403
404                return new CmsListIndependentAction("hide") {
405
406                    /**
407                     * @see org.opencms.workplace.list.CmsListIndependentAction#buttonHtml(org.opencms.workplace.CmsWorkplace)
408                     */
409                    @Override
410                    public String buttonHtml(CmsWorkplace wp) {
411
412                        return "";
413                    }
414                };
415            }
416        };
417        relationsDetailsPrint.setAtColumn(LIST_COLUMN_ROOT_PATH);
418        relationsDetailsPrint.setVisible(false);
419        relationsDetailsPrint.setPrintable(true);
420        relationsDetailsPrint.setFormatter(new CmsPublishBrokenRelationFormatter());
421
422        // add resources info item detail to meta data
423        metadata.addItemDetails(relationsDetailsPrint);
424    }
425
426    /**
427     * @see org.opencms.workplace.list.A_CmsListDialog#setMultiActions(org.opencms.workplace.list.CmsListMetadata)
428     */
429    @Override
430    protected void setMultiActions(CmsListMetadata metadata) {
431
432        // no LMAs, and remove default search action
433        metadata.setSearchAction(null);
434    }
435}