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.apps.modules;
029
030import org.opencms.file.CmsObject;
031import org.opencms.gwt.CmsCoreService;
032import org.opencms.main.CmsException;
033import org.opencms.main.CmsLog;
034import org.opencms.main.OpenCms;
035import org.opencms.module.CmsModule;
036import org.opencms.module.CmsModuleImportExportHandler;
037import org.opencms.report.A_CmsReportThread;
038import org.opencms.ui.A_CmsUI;
039import org.opencms.ui.CmsCssIcon;
040import org.opencms.ui.CmsVaadinUtils;
041import org.opencms.ui.FontOpenCms;
042import org.opencms.ui.apps.A_CmsAttributeAwareApp;
043import org.opencms.ui.apps.CmsAppView;
044import org.opencms.ui.apps.CmsAppView.CacheStatus;
045import org.opencms.ui.apps.CmsAppWorkplaceUi;
046import org.opencms.ui.apps.I_CmsAppUIContext;
047import org.opencms.ui.apps.I_CmsCachableApp;
048import org.opencms.ui.apps.Messages;
049import org.opencms.ui.apps.modules.edit.CmsEditModuleForm;
050import org.opencms.ui.components.CmsAppViewLayout;
051import org.opencms.ui.components.CmsBasicDialog;
052import org.opencms.ui.components.CmsBasicDialog.DialogWidth;
053import org.opencms.ui.components.CmsBasicReportPage;
054import org.opencms.ui.components.CmsConfirmationDialog;
055import org.opencms.ui.contextmenu.CmsMenuItemVisibilityMode;
056import org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry;
057import org.opencms.util.CmsStringUtil;
058
059import java.util.Arrays;
060import java.util.IdentityHashMap;
061import java.util.LinkedHashMap;
062import java.util.List;
063import java.util.Locale;
064import java.util.Map;
065import java.util.Set;
066
067import org.apache.commons.logging.Log;
068
069import com.google.common.collect.Lists;
070import com.google.common.collect.Maps;
071import com.vaadin.navigator.View;
072import com.vaadin.server.Resource;
073import com.vaadin.ui.Component;
074import com.vaadin.ui.UI;
075import com.vaadin.ui.Window;
076import com.vaadin.ui.themes.ValoTheme;
077import com.vaadin.v7.ui.TextField;
078
079/**
080 * Main module manager app class.<p>
081 */
082public class CmsModuleApp extends A_CmsAttributeAwareApp implements I_CmsCachableApp {
083
084    /**
085     * Additional app attributes for the module manager.<p>
086     */
087    public static class Attributes {
088
089        /** The buttons for the button bar. */
090        public static final String BUTTONS = "buttons";
091    }
092
093    /**
094     * Contains the icon constants for the module manager.<p>
095     */
096    public static class Icons {
097
098        /** Icon for the module manager app. */
099        public static Resource APP = new CmsCssIcon("oc-icon-32-module");
100
101        /** Icon for the 'import via http' button. */
102        public static Resource IMPORT = FontOpenCms.UPLOAD;
103
104        /** Icon for the module list. */
105        public static final Resource LIST_ICON = new CmsCssIcon("oc-icon-24-module");
106
107        /** Icon for resource info boxes. */
108        public static Resource RESINFO_ICON = new CmsCssIcon("oc-icon-24-module");
109
110    }
111
112    /**
113     * Contains the different navigation states for the module maanger.<p>
114     */
115    public static class States {
116
117        /** Delete report state. */
118        public static final String DELETE_REPORT = "delete";
119
120        /** Export report state. */
121        public static final String EXPORT_REPORT = "export";
122
123        /** State for 'import via http' form. */
124        public static final String IMPORT = "import";
125
126        /** State for 'iomport via http' report. */
127        public static final String IMPORT_REPORT = "import/report";
128
129        /** Main state. */
130        public static final String MAIN = "";
131    }
132
133    /**
134     * Context menu entry for deleting a module.<p>
135     */
136    class DeleteModuleEntry implements I_CmsSimpleContextMenuEntry<Set<String>> {
137
138        /**
139         * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#executeAction(java.lang.Object)
140         */
141        @SuppressWarnings("synthetic-access")
142        @Override
143        public void executeAction(final Set<String> context) {
144
145            try {
146                final String moduleName = context.iterator().next();
147                final CmsObject cms = OpenCms.initCmsObject(A_CmsUI.getCmsObject());
148                final CmsModule module = OpenCms.getModuleManager().getModule(moduleName);
149
150                Runnable okAction = new Runnable() {
151
152                    @Override
153                    public void run() {
154
155                        final A_CmsReportThread thread = new A_CmsReportThread(cms, "Delete module " + context) {
156
157                            @Override
158                            public String getReportUpdate() {
159
160                                return getReport().getReportUpdate();
161                            }
162
163                            @Override
164                            public void run() {
165
166                                initHtmlReport(OpenCms.getWorkplaceManager().getWorkplaceLocale(cms));
167                                try {
168                                    OpenCms.getModuleManager().deleteModule(cms, moduleName, false, getReport());
169                                } catch (Exception e) {
170                                    getReport().println(e);
171                                    LOG.error(e.getLocalizedMessage(), e);
172                                }
173
174                            }
175                        };
176                        if (module.hasModuleResourcesWithUndefinedSite()) {
177                            CmsSiteSelectDialog.openDialogInWindow(new CmsSiteSelectDialog.I_Callback() {
178
179                                @Override
180                                public void onCancel() {
181
182                                    // TODO Auto-generated method stub
183
184                                }
185
186                                @Override
187                                public void onSiteSelect(String site) {
188
189                                    cms.getRequestContext().setSiteRoot(site);
190                                    openReport(
191                                        CmsModuleApp.States.DELETE_REPORT,
192                                        thread,
193                                        CmsVaadinUtils.getMessageText(
194                                            Messages.GUI_MODULES_REPORT_DELETE_MODULE_1,
195                                            context));
196                                }
197                            }, CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_TITLE_SITE_SELECT_0));
198
199                        } else {
200                            openReport(
201                                CmsModuleApp.States.DELETE_REPORT,
202                                thread,
203                                CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_REPORT_DELETE_MODULE_1, context));
204                        }
205                    }
206                };
207                CmsConfirmationDialog.show(
208                    CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_CONFIRM_DELETE_TITLE_1, context),
209                    CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_DELETE_CONFIRMATION_0),
210                    okAction);
211            } catch (CmsException e) {
212                LOG.error(e.getLocalizedMessage(), e);
213            }
214
215        }
216
217        /**
218         * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#getTitle(java.util.Locale)
219         */
220        @Override
221        public String getTitle(Locale locale) {
222
223            return CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_CONTEXTMENU_DELETE_0);
224        }
225
226        /**
227         * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#getVisibility(java.lang.Object)
228         */
229        @Override
230        public CmsMenuItemVisibilityMode getVisibility(Set<String> context) {
231
232            if (context.size() > 1) {
233                return CmsMenuItemVisibilityMode.VISIBILITY_INVISIBLE;
234            }
235            return visibilityCheckHasModule(context.iterator().next());
236        }
237
238    }
239
240    /**
241     * Context menu entry for editng a module.
242     */
243    class EditModuleEntry implements I_CmsSimpleContextMenuEntry<Set<String>> {
244
245        /**
246         * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#executeAction(java.lang.Object)
247         */
248        @Override
249        public void executeAction(Set<String> context) {
250
251            CmsModuleApp.this.editModule(context.iterator().next());
252
253        }
254
255        /**
256         * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#getTitle(java.util.Locale)
257         */
258        @Override
259        public String getTitle(Locale locale) {
260
261            return CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_CONTEXTMENU_EDIT_0);
262        }
263
264        /**
265         * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#getVisibility(java.lang.Object)
266         */
267        @Override
268        public CmsMenuItemVisibilityMode getVisibility(Set<String> context) {
269
270            if (context.size() > 1) {
271                return CmsMenuItemVisibilityMode.VISIBILITY_INVISIBLE;
272            }
273            return visibilityCheckHasModule(context.iterator().next());
274        }
275
276    }
277
278    /**
279     * Context menu entry for editng a module.
280     */
281    static class ExplorerEntry implements I_CmsSimpleContextMenuEntry<Set<String>> {
282
283        /**
284         * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#executeAction(java.lang.Object)
285         */
286        @Override
287        public void executeAction(Set<String> context) {
288
289            String path = getModuleFolder(context.iterator().next());
290            if (path != null) {
291                String link = CmsCoreService.getVaadinWorkplaceLink(A_CmsUI.getCmsObject(), path);
292                A_CmsUI.get().getPage().setLocation(link);
293                A_CmsUI.get().getPage().reload();
294            }
295        }
296
297        /**
298         * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#getTitle(java.util.Locale)
299         */
300        @Override
301        public String getTitle(Locale locale) {
302
303            return CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_CONTEXTMENU_EXPLORER_0);
304        }
305
306        /**
307         * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#getVisibility(java.lang.Object)
308         */
309        @Override
310        public CmsMenuItemVisibilityMode getVisibility(Set<String> context) {
311
312            if (context.size() > 1) {
313                return CmsMenuItemVisibilityMode.VISIBILITY_INVISIBLE;
314            }
315            String moduleName = context.iterator().next();
316            if (getModuleFolder(moduleName) != null) {
317                return visibilityCheckHasModule(moduleName);
318            } else {
319                return CmsMenuItemVisibilityMode.VISIBILITY_INVISIBLE;
320            }
321        }
322
323        /**
324         * Tries to find the module folder under /system/modules for a given module.<p>
325         *
326         * @param moduleName the name of the module
327         *
328         * @return the module folder, or null if this module doesn't have one
329         */
330        private String getModuleFolder(String moduleName) {
331
332            CmsModule module = OpenCms.getModuleManager().getModule(moduleName);
333            if (module != null) {
334                for (String resource : module.getResources()) {
335                    if (CmsStringUtil.comparePaths("/system/modules/" + moduleName, resource)) {
336                        return resource;
337                    }
338                }
339            }
340            return null;
341        }
342    }
343
344    /**
345     * Context menu entry for exporting a module.
346     */
347    class ExportModuleEntry implements I_CmsSimpleContextMenuEntry<Set<String>> {
348
349        /**
350         * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#executeAction(java.lang.Object)
351         */
352        @Override
353        public void executeAction(final Set<String> context) {
354
355            final CmsObject cms = A_CmsUI.getCmsObject();
356            final String moduleName = context.iterator().next();
357            final String handlerDesc = CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_REPORT_EXPORT_1, moduleName);
358            final CmsModuleImportExportHandler handler = CmsModuleImportExportHandler.getExportHandler(
359                cms,
360                OpenCms.getModuleManager().getModule(moduleName),
361                handlerDesc);
362
363            final A_CmsReportThread thread = new A_CmsReportThread(cms, "Export module " + moduleName) {
364
365                @Override
366                public String getReportUpdate() {
367
368                    return getReport().getReportUpdate();
369                }
370
371                /**
372                 * @see java.lang.Thread#run()
373                 */
374                @SuppressWarnings("synthetic-access")
375                @Override
376                public void run() {
377
378                    initHtmlReport(OpenCms.getWorkplaceManager().getWorkplaceLocale(cms));
379                    try {
380                        OpenCms.getImportExportManager().exportData(cms, handler, getReport());
381                    } catch (Exception e) {
382                        getReport().println(e);
383                        LOG.error(e.getLocalizedMessage(), e);
384                    }
385
386                }
387            };
388            CmsModule module = OpenCms.getModuleManager().getModule(moduleName);
389            if (module.hasModuleResourcesWithUndefinedSite()) {
390                CmsSiteSelectDialog.openDialogInWindow(new CmsSiteSelectDialog.I_Callback() {
391
392                    @Override
393                    public void onCancel() {
394
395                        // TODO Auto-generated method stub
396
397                    }
398
399                    @Override
400                    public void onSiteSelect(String site) {
401
402                        cms.getRequestContext().setSiteRoot(site);
403                        Window window = CmsBasicDialog.prepareWindow(DialogWidth.wide);
404                        window.setCaption(CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_REPORT_EXPORT_1, context));
405                        CmsModuleExportDialog dialog = new CmsModuleExportDialog(handler, thread, window);
406                        window.setContent(dialog);
407                        A_CmsUI.get().addWindow(window);
408                        //                        openReport(
409                        //                            CmsModuleApp.States.EXPORT_REPORT,
410                        //                            thread,
411                        //                            CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_REPORT_EXPORT_1, context));
412                    }
413                }, CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_TITLE_SITE_SELECT_0));
414
415            } else {
416                Window window = CmsBasicDialog.prepareWindow(DialogWidth.wide);
417                window.setHeight("500px");
418                window.setCaption(CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_REPORT_EXPORT_1, context));
419                CmsModuleExportDialog dialog = new CmsModuleExportDialog(handler, thread, window);
420                window.setContent(dialog);
421                A_CmsUI.get().addWindow(window);
422                //                openReport(
423                //                    CmsModuleApp.States.EXPORT_REPORT,
424                //                    thread,
425                //                    CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_REPORT_EXPORT_1, context));
426            }
427        }
428
429        /**
430         * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#getTitle(java.util.Locale)
431         */
432        @Override
433        public String getTitle(Locale locale) {
434
435            return CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_CONTEXTMENU_EXPORT_0);
436        }
437
438        /**
439         * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#getVisibility(java.lang.Object)
440         */
441        @Override
442        public CmsMenuItemVisibilityMode getVisibility(Set<String> context) {
443
444            if (context.size() > 1) {
445                return CmsMenuItemVisibilityMode.VISIBILITY_INVISIBLE;
446            }
447
448            return visibilityCheckHasModule(context.iterator().next());
449        }
450
451    }
452
453    /**
454     * Context menu entry for displaying the type list.<p>
455     */
456    class ModuleInfoEntry
457    implements I_CmsSimpleContextMenuEntry<Set<String>>,
458    org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry.I_HasCssStyles {
459
460        /**
461         * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#executeAction(java.lang.Object)
462         */
463        @Override
464        public void executeAction(Set<String> module) {
465
466            Window window = CmsBasicDialog.prepareWindow(DialogWidth.wide);
467
468            CmsModuleInfoDialog typeList = new CmsModuleInfoDialog(
469                module.iterator().next(),
470                CmsModuleApp.this::editModule);
471
472            window.setContent(typeList);
473            window.setCaption(CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_TYPES_FOR_MODULE_0));
474            A_CmsUI.get().addWindow(window);
475            window.center();
476
477        }
478
479        /**
480         * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry.I_HasCssStyles#getStyles()
481         */
482        public String getStyles() {
483
484            return ValoTheme.LABEL_BOLD;
485        }
486
487        /**
488         * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#getTitle(java.util.Locale)
489         */
490        @Override
491        public String getTitle(Locale locale) {
492
493            return CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_CONTEXTMENU_LIST_TYPES_0);
494        }
495
496        /**
497         * @see org.opencms.ui.contextmenu.I_CmsSimpleContextMenuEntry#getVisibility(java.lang.Object)
498         */
499        @Override
500        public CmsMenuItemVisibilityMode getVisibility(Set<String> context) {
501
502            if (context.size() > 1) {
503                return CmsMenuItemVisibilityMode.VISIBILITY_INVISIBLE;
504            }
505            return visibilityCheckHasModule(context.iterator().next());
506        }
507
508    }
509
510    /** The 'module' parameter. */
511    public static final String PARAM_MODULE = "module";
512
513    /** Logger instance for this class. */
514    private static final Log LOG = CmsLog.getLog(CmsModuleApp.class);
515
516    /** Serial version id. */
517    private static final long serialVersionUID = 1L;
518
519    /** Contains labels for the running reports. */
520    private IdentityHashMap<A_CmsReportThread, String> m_labels = new IdentityHashMap<A_CmsReportThread, String>();
521
522    /** Map of running reports with the module manager app states they belong to as keys. */
523    private Map<String, A_CmsReportThread> m_reports = Maps.newHashMap();
524
525    /**
526     * Creates a new instance.<p>
527     */
528    public CmsModuleApp() {
529        // do nothing
530
531    }
532
533    /**
534     * Opens the module editor for the given module.<p>
535     *
536     * @param module the edited module
537     * @param isNew true if this is a new module
538     * @param caption the caption for the module editor dialog
539     * @param callback the callback to call after the edit dialog is done
540     */
541    public static void editModule(CmsModule module, boolean isNew, String caption, Runnable callback) {
542
543        Window window = CmsBasicDialog.prepareWindow(DialogWidth.wide);
544        CmsEditModuleForm form = new CmsEditModuleForm(module, isNew, callback);
545        window.setContent(form);
546        window.setCaption(caption);
547        A_CmsUI.get().addWindow(window);
548        window.center();
549    }
550
551    /**
552     * Returns VISIBILITY_ACTIVE if a module with the given name exists, and VISIBILITY_INVISIBLE otherwise. <p>
553     *
554     * @param name a module name
555     * @return the visibility
556     */
557    public static CmsMenuItemVisibilityMode visibilityCheckHasModule(String name) {
558
559        if (OpenCms.getModuleManager().hasModule(name)) {
560            return CmsMenuItemVisibilityMode.VISIBILITY_ACTIVE;
561        } else {
562            return CmsMenuItemVisibilityMode.VISIBILITY_INVISIBLE;
563        }
564    }
565
566    /**
567     * Opens the edit dialog for the given module.<p>
568     *
569     * @param moduleName the name of the module
570     */
571    public void editModule(String moduleName) {
572
573        StringBuilder searchFilterBuffer = new StringBuilder();
574        CmsVaadinUtils.visitDescendants(UI.getCurrent(), component -> {
575            if (component instanceof CmsModuleTable) {
576                TextField searchBox = ((CmsModuleTable)component).getSearchBox();
577                if (searchBox != null) {
578                    searchFilterBuffer.append(searchBox.getValue());
579                }
580                return false;
581            } else {
582                return true;
583            }
584        });
585        String filter = searchFilterBuffer.toString();
586        CmsModule module = OpenCms.getModuleManager().getModule(moduleName);
587        editModule(
588            module,
589            false,
590            CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_TITLE_EDIT_MODULE_1, module.getName()),
591            () -> {
592                reload();
593                // Setting the filter again is redundant for this class, but might be needed for subclasses, as the actual table instance may change
594                CmsVaadinUtils.visitDescendants(UI.getCurrent(), component -> {
595                    if (component instanceof CmsModuleTable) {
596                        ((CmsModuleTable)component).filter(filter);
597                        return false;
598                    } else {
599                        return true;
600                    }
601                });
602
603            });
604    }
605
606    /**
607     * Opens module edit dialog for a new module.<p>
608     *
609     * @param callback the callback to call after finishing
610     */
611    public void editNewModule(Runnable callback) {
612
613        CmsModule module = new CmsModule();
614        module.setSite("/");
615
616        editModule(module, true, CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_TITLE_NEW_MODULE_0), callback);
617
618    }
619
620    /**
621     * Returns the available menu entries.<p>
622     *
623     * @return the menu entries
624     */
625    public List<I_CmsSimpleContextMenuEntry<Set<String>>> getMenuEntries() {
626
627        List<I_CmsSimpleContextMenuEntry<Set<String>>> result = Lists.newArrayList();
628
629        result.add(new ModuleInfoEntry());
630        result.add(new EditModuleEntry());
631        result.add(new DeleteModuleEntry());
632        result.add(new ExportModuleEntry());
633        result.add(new ExplorerEntry());
634        return result;
635    }
636
637    /**
638     * @see org.opencms.ui.apps.A_CmsWorkplaceApp#initUI(org.opencms.ui.apps.I_CmsAppUIContext)
639     */
640    @Override
641    public void initUI(I_CmsAppUIContext context) {
642
643        context.addPublishButton(updatedItems -> {});
644        super.initUI(context);
645    }
646
647    /**
648     * @see org.opencms.ui.apps.I_CmsCachableApp#isCachable()
649     */
650    public boolean isCachable() {
651
652        return true;
653    }
654
655    /**
656     * @see org.opencms.ui.apps.I_CmsCachableApp#onRestoreFromCache()
657     */
658    public void onRestoreFromCache() {
659
660        // Do nothing
661
662    }
663
664    /**
665     * @see org.opencms.ui.apps.A_CmsWorkplaceApp#onStateChange(java.lang.String)
666     */
667    @Override
668    public void onStateChange(String state) {
669
670        View view = CmsAppWorkplaceUi.get().getCurrentView();
671        ((CmsAppView)view).setCacheStatus(CacheStatus.cache);
672        super.onStateChange(state);
673
674    }
675
676    /**
677     * Opens the module info dialog.<p>
678     *
679     * @param name the name of the module
680     */
681    public void openModuleInfo(Set<String> name) {
682
683        new ModuleInfoEntry().executeAction(name);
684
685    }
686
687    /**
688     * Changes to a new sub-view and stores a report to be displayed by that subview.<p<
689     *
690     * @param newState the new state
691     * @param thread the report thread which should be displayed in the sub view
692     * @param label the label to display for the report
693     */
694    public void openReport(String newState, A_CmsReportThread thread, String label) {
695
696        setReport(newState, thread);
697        m_labels.put(thread, label);
698        openSubView(newState, true);
699    }
700
701    /**
702     * Stores a report thread isntance under a given key.<p>
703     *
704     * @param key the key
705     * @param report the report thread instance
706     */
707    public void setReport(String key, A_CmsReportThread report) {
708
709        m_reports.put(key, report);
710
711    }
712
713    /**
714     * @see org.opencms.ui.apps.A_CmsWorkplaceApp#getBreadCrumbForState(java.lang.String)
715     */
716    @Override
717    protected LinkedHashMap<String, String> getBreadCrumbForState(String state) {
718
719        String noParamState = state.replaceFirst("!!.*$", "");
720        List<String> tokens = Lists.newArrayList();
721        String appId = CmsModuleAppConfiguration.APP_ID;
722        tokens.add(appId);
723        tokens.addAll(Arrays.asList(noParamState.split("/")));
724        LinkedHashMap<String, String> breadcrumbs = new LinkedHashMap<String, String>();
725        List<String> currentPath = Lists.newArrayList();
726        breadcrumbs.put(appId, appId);
727        String lastKey = appId;
728
729        for (int i = 0; i < tokens.size(); i++) {
730            if (CmsStringUtil.isEmptyOrWhitespaceOnly(tokens.get(i))) {
731                continue;
732            }
733            currentPath.add(tokens.get(i));
734            String key = CmsStringUtil.listAsString(currentPath, "/");
735            String text = null;
736            if (tokens.get(i).equals(appId)) {
737                text = CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_NAV_MAIN_0);
738            } else if (tokens.get(i).equals("delete")) {
739                text = CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_NAV_DELETE_MODULE_0);
740            } else if (tokens.get(i).equals("export")) {
741                text = CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_NAV_EXPORT_MODULE_0);
742            } else if (tokens.get(i).equals("import")) {
743                text = CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_NAV_IMPORT_HTTP_0);
744            } else if (tokens.get(i).equals("server-import")) {
745                text = CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_NAV_IMPORT_SERVER_0);
746            } else if (tokens.get(i).equals("report")) {
747                text = CmsVaadinUtils.getMessageText(Messages.GUI_MODULES_NAV_REPORT_0);
748            } else {
749                text = tokens.get(i);
750            }
751            breadcrumbs.put(key, text);
752            lastKey = key;
753        }
754        String lastLabel = breadcrumbs.remove(lastKey);
755        breadcrumbs.put("", lastLabel);
756        return breadcrumbs;
757    }
758
759    /**
760     *
761     * @see org.opencms.ui.apps.A_CmsWorkplaceApp#getComponentForState(java.lang.String)
762     */
763    @Override
764    protected Component getComponentForState(String state) {
765
766        if (state.equals(States.IMPORT)) {
767            return new CmsImportTabForm(this, this::reload);
768        } else if (state.equals(States.IMPORT_REPORT)
769            || state.equals(States.DELETE_REPORT)
770            || state.equals(States.EXPORT_REPORT)) {
771            String label = getReportLabel(state);
772            CmsBasicReportPage reportForm = new CmsBasicReportPage(label, m_reports.get(state), new Runnable() {
773
774                public void run() {
775
776                    openSubView("", true);
777                }
778            });
779            reportForm.setHeight("100%");
780            return reportForm;
781        } else {
782            return getModuleTable();
783        }
784    }
785
786    /**
787     * Gets the module table.<p>
788     *
789     * @return the module table
790     */
791    protected Component getModuleTable() {
792
793        List<CmsModuleRow> rows = Lists.newArrayList();
794        for (CmsModule module : OpenCms.getModuleManager().getAllInstalledModules()) {
795            CmsModuleRow row = new CmsModuleRow(module);
796            rows.add(row);
797        }
798        CmsModuleTable<CmsModuleRow> table = new CmsModuleTable<CmsModuleRow>(this, CmsModuleRow.class, rows);
799        return table;
800    }
801
802    /**
803     * Gets the label for a given report.<p>
804     *
805     * @param state the state for which to get the label
806     * @return the label
807     */
808    protected String getReportLabel(String state) {
809
810        return m_labels.get(m_reports.get(state));
811    }
812
813    /**
814     * @see org.opencms.ui.apps.A_CmsWorkplaceApp#getSubNavEntries(java.lang.String)
815     */
816    @Override
817    protected List<NavEntry> getSubNavEntries(String state) {
818
819        return null;
820    }
821
822    /**
823     * Reloads the table.
824     */
825    protected void reload() {
826
827        CmsVaadinUtils.visitDescendants(UI.getCurrent(), component -> {
828            if (component instanceof CmsModuleTable) {
829                ((CmsModuleTable)component).reload();
830                return false;
831            } else {
832                return true;
833            }
834        });
835
836    }
837
838    /**
839     * @see org.opencms.ui.apps.A_CmsAttributeAwareApp#updateAppAttributes(java.util.Map)
840     */
841    @Override
842    protected void updateAppAttributes(Map<String, Object> attributes) {
843
844        super.updateAppAttributes(attributes);
845        m_uiContext.clearToolbarButtons();
846        @SuppressWarnings("unchecked")
847        List<Component> buttons = (List<Component>)attributes.get(Attributes.BUTTONS);
848        if (buttons != null) {
849            buttons.add(0, CmsAppViewLayout.createPublishButton(changes -> {}));
850            for (Component button : buttons) {
851                m_uiContext.addToolbarButton(button);
852            }
853        }
854    }
855
856}