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