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.tools.content.languagecopy;
029
030import org.opencms.file.CmsObject;
031import org.opencms.file.CmsProperty;
032import org.opencms.file.CmsPropertyDefinition;
033import org.opencms.file.CmsResource;
034import org.opencms.file.CmsResourceFilter;
035import org.opencms.file.types.CmsResourceTypeXmlContent;
036import org.opencms.file.types.CmsResourceTypeXmlPage;
037import org.opencms.file.types.I_CmsResourceType;
038import org.opencms.i18n.CmsMessageContainer;
039import org.opencms.jsp.CmsJspActionElement;
040import org.opencms.main.CmsException;
041import org.opencms.main.CmsLog;
042import org.opencms.main.CmsRuntimeException;
043import org.opencms.main.OpenCms;
044import org.opencms.util.CmsStringUtil;
045import org.opencms.workplace.CmsWorkplace;
046import org.opencms.workplace.CmsWorkplaceSettings;
047import org.opencms.workplace.list.A_CmsListDialog;
048import org.opencms.workplace.list.CmsListColumnAlignEnum;
049import org.opencms.workplace.list.CmsListColumnDefinition;
050import org.opencms.workplace.list.CmsListItem;
051import org.opencms.workplace.list.CmsListMetadata;
052import org.opencms.workplace.list.CmsListMultiAction;
053import org.opencms.workplace.list.CmsListOrderEnum;
054import org.opencms.workplace.tools.CmsToolDialog;
055import org.opencms.workplace.tools.CmsToolManager;
056import org.opencms.xml.content.CmsXmlContent;
057import org.opencms.xml.content.CmsXmlContentFactory;
058
059import java.io.FileNotFoundException;
060import java.io.IOException;
061import java.util.ArrayList;
062import java.util.Collections;
063import java.util.HashMap;
064import java.util.LinkedList;
065import java.util.List;
066import java.util.Locale;
067import java.util.Map;
068
069import javax.servlet.ServletException;
070import javax.servlet.http.HttpServletRequest;
071import javax.servlet.http.HttpServletResponse;
072import javax.servlet.jsp.PageContext;
073
074import org.apache.commons.logging.Log;
075
076/**
077 * A list that displays resources and the existance of their language nodes.
078 * <p>
079 *
080 * @since 7.5.1
081 *
082 */
083public class CmsLanguageCopySelectionList extends A_CmsListDialog {
084
085    /** list action id constant. */
086    public static final String LIST_ACTION_NONE = "an";
087
088    /** list column id constant. */
089    public static final String LIST_COLUMN_ICON = "lcic";
090
091    /** list action id constant. */
092    public static final String LIST_COLUMN_ID = "li.id.languagecopyselection";
093
094    /** list column id constant. */
095    public static final String LIST_COLUMN_PATH = "lcp";
096
097    /** list column id constant. */
098    public static final String LIST_COLUMN_PREFIX_PROPERTY = "cnp-";
099
100    /** list column id constant. */
101    public static final String LIST_COLUMN_RESOURCETYPE = "lcrt";
102
103    /** list item detail id constant. */
104    public static final String LIST_DETAIL_FULLPATH = "df";
105
106    /** Multi action for copy. */
107    public static final String LIST_MACTION_COPY = "mac";
108
109    /** The request parameter for the paths to work on. */
110    public static final String PARAM_PATHS = "paths";
111
112    /** The request parameter for the paths to work on. */
113    public static final String PARAM_SIBLINGS = "siblings";
114
115    /** The request parameter for the source language. */
116    public static final String PARAM_SOURCE_LANGUAGE = "sourcelanguage";
117
118    /** The request parameter for the target language. */
119    public static final String PARAM_TARGET_LANGUAGE = "targetlanguage";
120
121    /** The request parameter for the target language. */
122    public static final String PARAM_DELETE = "delete";
123
124    /** The log object for this class. */
125    private static final Log LOG = CmsLog.getLog(CmsLanguageCopySelectionList.class);
126
127    /** Signals whether to delete the original language node or not. */
128    private String m_paramDelete;
129
130    /** The source language. */
131    private String m_paramSourcelanguage;
132
133    /** The target language. */
134    private String m_paramTargetlanguage;
135
136    /** The paths. */
137    private String[] m_paths;
138
139    /**
140     * Public constructor.
141     * <p>
142     *
143     * @param jsp an initialized JSP action element
144     *
145     * @throws CmsException if something goes wrong.
146     *
147     * @throws FileNotFoundException if something goes wrong.
148     */
149    public CmsLanguageCopySelectionList(final CmsJspActionElement jsp)
150    throws FileNotFoundException, CmsException {
151
152        this(jsp, LIST_COLUMN_ID, Messages.get().container(Messages.GUI_LIST_LANGUAGECOPY_NAME_0));
153    }
154
155    /**
156     * Public constructor.
157     * <p>
158     *
159     * @param jsp an initialized JSP action element
160     * @param listId the id of the list
161     * @param listName the list name
162     *
163     * @throws CmsException if something goes wrong.
164     *
165     * @throws FileNotFoundException if something goes wrong.
166     */
167    public CmsLanguageCopySelectionList(
168        final CmsJspActionElement jsp,
169        final String listId,
170        final CmsMessageContainer listName)
171        throws FileNotFoundException, CmsException {
172
173        this(jsp, listId, listName, LIST_COLUMN_ID, CmsListOrderEnum.ORDER_ASCENDING, null);
174    }
175
176    /**
177     * Public constructor.
178     * <p>
179     *
180     * @param jsp an initialized JSP action element
181     * @param listId the id of the displayed list
182     * @param listName the name of the list
183     * @param sortedColId the a priory sorted column
184     * @param sortOrder the order of the sorted column
185     * @param searchableColId the column to search into
186     *
187     * @throws CmsException if something goes wrong.
188     * @throws FileNotFoundException if something goes wrong.
189     */
190    @SuppressWarnings("unused")
191    public CmsLanguageCopySelectionList(
192        final CmsJspActionElement jsp,
193        final String listId,
194        final CmsMessageContainer listName,
195        final String sortedColId,
196        final CmsListOrderEnum sortOrder,
197        final String searchableColId)
198        throws FileNotFoundException, CmsException {
199
200        super(jsp, listId, listName, sortedColId, sortOrder, searchableColId);
201    }
202
203    /**
204     * Public constructor with JSP variables.
205     * <p>
206     *
207     * @param context the JSP page context
208     * @param req the JSP request
209     * @param res the JSP response
210     *
211     * @throws CmsException if something goes wrong.
212     * @throws FileNotFoundException if something goes wrong.
213     */
214    public CmsLanguageCopySelectionList(
215        final PageContext context,
216        final HttpServletRequest req,
217        final HttpServletResponse res)
218        throws FileNotFoundException, CmsException {
219
220        this(new CmsJspActionElement(context, req, res));
221    }
222
223    /**
224     * @see org.opencms.workplace.list.A_CmsListDialog#executeListMultiActions()
225     */
226    @Override
227    public void executeListMultiActions() throws IOException, ServletException, CmsRuntimeException {
228
229        if (getParamListAction().equals(LIST_MACTION_COPY)) {
230
231            // create absolute RFS path and store it in dialog object
232            Map<String, String[]> params = new HashMap<String, String[]>();
233            List<CmsListItem> items = getSelectedItems();
234            List<String> paths = new LinkedList<String>();
235            for (CmsListItem item : items) {
236                paths.add(String.valueOf(item.get(LIST_COLUMN_PATH)));
237            }
238            params.put(
239                CmsLanguageCopyFolderAndLanguageSelectDialog.PARAM_COPYRESOURCES,
240                new String[] {CmsStringUtil.listAsString(paths, ",")});
241            params.put(PARAM_DELETE, new String[] {getParamDelete()});
242            // the source language
243            params.put(PARAM_SOURCE_LANGUAGE, new String[] {getParamSourcelanguage()});
244            // the target language
245            params.put(PARAM_TARGET_LANGUAGE, new String[] {getParamTargetlanguage()});
246            // set style to display report in correct layout
247            params.put(PARAM_STYLE, new String[] {CmsToolDialog.STYLE_NEW});
248            // set close link to get back to overview after finishing the import
249            params.put(PARAM_CLOSELINK, new String[] {CmsToolManager.linkForToolPath(getJsp(), "/contenttools")});
250            // redirect to the report output JSP
251            getToolManager().jspForwardPage(
252                this,
253                CmsWorkplace.PATH_WORKPLACE + "admin/contenttools/languagecopy/report.jsp",
254                params);
255        }
256        listSave();
257    }
258
259    /**
260     * @see org.opencms.workplace.list.A_CmsListDialog#executeListSingleActions()
261     */
262    @SuppressWarnings("unused")
263    @Override
264    public void executeListSingleActions() throws IOException, ServletException, CmsRuntimeException {
265
266        // do nothing
267    }
268
269    /**
270     * @return the resourcses to copy
271     */
272    public String[] getCopyResources() {
273
274        List<CmsListItem> items = getSelectedItems();
275        String paths = "";
276        boolean initial = true;
277        for (CmsListItem item : items) {
278            if (!initial) {
279                paths.concat(",");
280            }
281            paths.concat(String.valueOf(item.get(LIST_COLUMN_PATH)));
282            initial = false;
283        }
284        return CmsStringUtil.splitAsArray(paths, ",");
285    }
286
287    /**
288     * @return the paths
289     */
290    public String getParamPaths() {
291
292        return CmsStringUtil.arrayAsString(m_paths, ",");
293    }
294
295    /**
296    * @return the source language
297    */
298    public String getParamSourcelanguage() {
299
300        return m_paramSourcelanguage;
301    }
302
303    /**
304     * @return the target language
305     */
306    public String getParamTargetlanguage() {
307
308        return m_paramTargetlanguage;
309    }
310
311    /**
312     * Returns the paramDelete.<p>
313     *
314     * @return the paramDelete
315     */
316    public String getParamDelete() {
317
318        return m_paramDelete;
319    }
320
321    /**
322     * Sets the paramDelete.<p>
323     *
324     * @param paramDelete the paramDelete to set
325     */
326    public void setParamDelete(String paramDelete) {
327
328        m_paramDelete = paramDelete;
329    }
330
331    /**
332     * @param paths
333     *            the paths to set
334     */
335    public void setParamPaths(final String paths) {
336
337        m_paths = CmsStringUtil.splitAsArray(paths, ",");
338    }
339
340    /**
341     * @param sourceLanguage
342     *            the source language
343     */
344    public void setParamSourcelanguage(String sourceLanguage) {
345
346        m_paramSourcelanguage = sourceLanguage;
347    }
348
349    /**
350     * @param targetLanguage
351     *            the target language
352     */
353    public void setParamTargetlanguage(String targetLanguage) {
354
355        m_paramTargetlanguage = targetLanguage;
356    }
357
358    /**
359     * @see org.opencms.workplace.list.A_CmsListDialog#fillDetails(java.lang.String)
360     */
361    @Override
362    protected void fillDetails(final String detailId) {
363
364        // do nothing
365    }
366
367    /**
368     * @see org.opencms.workplace.list.A_CmsListDialog#getListItems()
369     */
370    @Override
371    protected List<CmsListItem> getListItems() {
372
373        List<CmsListItem> result = new ArrayList<CmsListItem>();
374        // get content
375        CmsListItem item;
376        int idCounter = 0;
377        for (CmsResource resource : getResources()) {
378            item = getList().newItem(resource.getRootPath());
379            fillItem(resource, item, idCounter);
380            idCounter++;
381            result.add(item);
382        }
383        return result;
384    }
385
386    /**
387     * @see org.opencms.workplace.CmsWorkplace#initMessages()
388     */
389    @Override
390    protected void initMessages() {
391
392        // add specific dialog resource bundle
393        addMessages(Messages.get().getBundleName());
394        // add default resource bundles
395        super.initMessages();
396    }
397
398    /**
399     * @see org.opencms.workplace.list.A_CmsListDialog#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings,
400     *      javax.servlet.http.HttpServletRequest)
401     */
402    @Override
403    protected void initWorkplaceRequestValues(final CmsWorkplaceSettings settings, final HttpServletRequest request) {
404
405        super.initWorkplaceRequestValues(settings, request);
406    }
407
408    /**
409     * @see org.opencms.workplace.list.A_CmsListDialog#setColumns(org.opencms.workplace.list.CmsListMetadata)
410     */
411    @Override
412    protected void setColumns(final CmsListMetadata metadata) {
413
414        // enforce re-invocation of this method because columns are varying and must not be cached:
415        metadata.setVolatile(true);
416
417        // add column for icon
418        CmsListColumnDefinition iconCol = new CmsListColumnDefinition(LIST_COLUMN_ICON);
419        iconCol.setName(Messages.get().container(Messages.GUI_LIST_LANGUAGECOPY_COL_ICON_NAME_0));
420        iconCol.setHelpText(Messages.get().container(Messages.GUI_LIST_LANGUAGECOPY_COL_ICON_HELP_0));
421        iconCol.setAlign(CmsListColumnAlignEnum.ALIGN_LEFT);
422        iconCol.setWidth("16");
423        iconCol.setSorteable(false);
424        metadata.addColumn(iconCol);
425        iconCol.setPrintable(true);
426
427        // add column for name
428        CmsListColumnDefinition nameCol = new CmsListColumnDefinition(LIST_COLUMN_PATH);
429        nameCol.setName(Messages.get().container(Messages.GUI_LIST_LANGUAGECOPY_COL_PATH_NAME_0));
430        nameCol.setHelpText(Messages.get().container(Messages.GUI_LIST_LANGUAGECOPY_COL_PATH_HELP_0));
431        nameCol.setAlign(CmsListColumnAlignEnum.ALIGN_LEFT);
432        nameCol.setSorteable(true);
433        metadata.addColumn(nameCol);
434        nameCol.setPrintable(true);
435
436        // add column for resource type
437        CmsListColumnDefinition typeCol = new CmsListColumnDefinition(LIST_COLUMN_RESOURCETYPE);
438        typeCol.setName(Messages.get().container(Messages.GUI_LIST_LANGUAGECOPY_COL_RESOURCETYPE_NAME_0));
439        typeCol.setHelpText(Messages.get().container(Messages.GUI_LIST_LANGUAGECOPY_COL_RESOURCETYPE_HELP_0));
440        typeCol.setAlign(CmsListColumnAlignEnum.ALIGN_LEFT);
441        typeCol.setSorteable(true);
442        metadata.addColumn(typeCol);
443        typeCol.setPrintable(true);
444
445        // add columns for languages:
446        List<Locale> sysLocales = OpenCms.getLocaleManager().getAvailableLocales();
447        CmsListColumnDefinition langCol;
448        for (Locale locale : sysLocales) {
449            langCol = new CmsListColumnDefinition(locale.toString());
450            langCol.setName(
451                Messages.get().container(
452                    Messages.GUI_LIST_LANGUAGECOPY_COL_LANGUAGE_NAME_1,
453                    new Object[] {locale.toString()}));
454            langCol.setHelpText(Messages.get().container(Messages.GUI_LIST_LANGUAGECOPY_COL_LANGUAGE_HELP_0));
455            langCol.setAlign(CmsListColumnAlignEnum.ALIGN_LEFT);
456            langCol.setSorteable(false);
457            metadata.addColumn(langCol);
458            langCol.setPrintable(true);
459        }
460
461    }
462
463    /**
464     * @see org.opencms.workplace.list.A_CmsListDialog#setIndependentActions(org.opencms.workplace.list.CmsListMetadata)
465     */
466    @Override
467    protected void setIndependentActions(final CmsListMetadata metadata) {
468
469        // nothing to do here
470    }
471
472    /**
473     * @see org.opencms.workplace.list.A_CmsListDialog#setMultiActions(org.opencms.workplace.list.CmsListMetadata)
474     */
475    @Override
476    protected void setMultiActions(final CmsListMetadata metadata) {
477
478        // add copy multi action
479        CmsListMultiAction copyAction = new CmsListMultiAction(LIST_MACTION_COPY);
480        copyAction.setName(Messages.get().container(Messages.GUI_LIST_SEARCHINDEX_MACTION_COPY_NAME_0));
481        copyAction.setHelpText(Messages.get().container(Messages.GUI_LIST_SEARCHINDEX_MACTION_COPY_HELP_0));
482        copyAction.setIconPath(ICON_MULTI_ADD);
483        metadata.addMultiAction(copyAction);
484    }
485
486    /**
487     * Fills a single item.
488     * <p>
489     *
490     * @param resource the corresponding resource.
491     * @param item the item to fill.
492     * @param id used for the ID column.
493     */
494    private void fillItem(final CmsResource resource, final CmsListItem item, final int id) {
495
496        CmsObject cms = getCms();
497        CmsXmlContent xmlContent;
498
499        I_CmsResourceType type;
500        String iconPath;
501
502        // fill path column:
503        String sitePath = cms.getSitePath(resource);
504        item.set(LIST_COLUMN_PATH, sitePath);
505
506        // fill language node existence column:
507        item.set(LIST_COLUMN_PATH, sitePath);
508        boolean languageNodeExists = false;
509        String languageNodeHtml;
510
511        List<Locale> sysLocales = OpenCms.getLocaleManager().getAvailableLocales();
512        try {
513            xmlContent = CmsXmlContentFactory.unmarshal(cms, cms.readFile(resource));
514            for (Locale locale : sysLocales) {
515                languageNodeExists = xmlContent.hasLocale(locale);
516                if (languageNodeExists) {
517                    languageNodeHtml = "<input type=\"checkbox\" checked=\"checked\" disabled=\"disabled\"/>";
518                } else {
519                    languageNodeHtml = "<input type=\"checkbox\" disabled=\"disabled\"/>";
520                }
521                item.set(locale.toString(), languageNodeHtml);
522
523            }
524        } catch (Throwable e1) {
525            LOG.error(Messages.get().getBundle().key(Messages.LOG_ERR_LANGUAGECOPY_DETERMINE_LANGUAGE_NODE_1), e1);
526            languageNodeHtml = "n/a";
527            for (Locale locale : sysLocales) {
528                item.set(locale.toString(), languageNodeHtml);
529            }
530        }
531
532        // type column:
533        type = OpenCms.getResourceManager().getResourceType(resource);
534        item.set(LIST_COLUMN_RESOURCETYPE, type.getTypeName());
535
536        // icon column with title property for tooltip:
537        String title = "";
538        try {
539            CmsProperty titleProperty = cms.readPropertyObject(resource, CmsPropertyDefinition.PROPERTY_TITLE, true);
540            title = titleProperty.getValue();
541        } catch (CmsException e) {
542            LOG.warn(Messages.get().getBundle().key(Messages.LOG_WARN_LANGUAGECOPY_READPROP_1), e);
543        }
544
545        iconPath = getSkinUri()
546            + CmsWorkplace.RES_PATH_FILETYPES
547            + OpenCms.getWorkplaceManager().getExplorerTypeSetting(type.getTypeName()).getIcon();
548        String iconImage;
549        iconImage = "<img src=\"" + iconPath + "\" alt=\"" + type.getTypeName() + "\" title=\"" + title + "\" />";
550        item.set(LIST_COLUMN_ICON, iconImage);
551    }
552
553    /**
554     * Reads the resources available for processing based on the path parameters.<p>
555     *
556     * @return the resources available for processing based on the path parameters.
557     */
558    private List<CmsResource> getResources() {
559
560        List<CmsResource> result = new LinkedList<CmsResource>();
561        CmsObject cms = getCms();
562        CmsResourceFilter filter = CmsResourceFilter.ALL;
563        try {
564            for (String path : m_paths) {
565                List<CmsResource> resources = cms.readResources(path, filter, true);
566                // filter out any resource that is no XML content:
567                for (CmsResource resource : resources) {
568                    if (resource.isFile()) {
569                        if (CmsResourceTypeXmlContent.isXmlContent(resource)) {
570                            result.add(resource);
571                        } else if (CmsResourceTypeXmlPage.isXmlPage(resource)) {
572                            result.add(resource);
573                        }
574                    }
575                }
576            }
577        } catch (CmsException e) {
578            LOG.error(Messages.get().getBundle().key(Messages.LOG_ERR_LANGUAGECOPY_READRESOURCES_0), e);
579            result = Collections.emptyList();
580        }
581
582        return result;
583    }
584}