View Javadoc

1   /**
2    * This file Copyright (c) 2013-2014 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.pages.app.editor;
35  
36  import info.magnolia.cms.core.version.VersionManager;
37  import info.magnolia.cms.i18n.I18nContentSupport;
38  import info.magnolia.context.MgnlContext;
39  import info.magnolia.event.EventBus;
40  import info.magnolia.i18nsystem.SimpleTranslator;
41  import info.magnolia.jcr.util.NodeTypes;
42  import info.magnolia.jcr.util.NodeUtil;
43  import info.magnolia.jcr.util.PropertyUtil;
44  import info.magnolia.jcr.util.SessionUtil;
45  import info.magnolia.link.LinkUtil;
46  import info.magnolia.objectfactory.Components;
47  import info.magnolia.pages.app.editor.event.ComponentMoveEvent;
48  import info.magnolia.pages.app.editor.event.NodeSelectedEvent;
49  import info.magnolia.repository.RepositoryConstants;
50  import info.magnolia.ui.actionbar.ActionbarPresenter;
51  import info.magnolia.ui.actionbar.ActionbarView;
52  import info.magnolia.ui.actionbar.definition.ActionbarDefinition;
53  import info.magnolia.ui.actionbar.definition.ActionbarGroupDefinition;
54  import info.magnolia.ui.actionbar.definition.ActionbarItemDefinition;
55  import info.magnolia.ui.actionbar.definition.ActionbarSectionDefinition;
56  import info.magnolia.ui.api.action.ActionDefinition;
57  import info.magnolia.ui.api.action.ActionExecutionException;
58  import info.magnolia.ui.api.action.ActionExecutor;
59  import info.magnolia.ui.api.app.AppContext;
60  import info.magnolia.ui.api.app.SubAppContext;
61  import info.magnolia.ui.api.app.SubAppEventBus;
62  import info.magnolia.ui.api.availability.AvailabilityChecker;
63  import info.magnolia.ui.api.availability.AvailabilityDefinition;
64  import info.magnolia.ui.api.event.AdmincentralEventBus;
65  import info.magnolia.ui.api.event.ContentChangedEvent;
66  import info.magnolia.ui.api.i18n.I18NAuthoringSupport;
67  import info.magnolia.ui.api.location.Location;
68  import info.magnolia.ui.api.location.LocationChangedEvent;
69  import info.magnolia.ui.api.message.Message;
70  import info.magnolia.ui.api.message.MessageType;
71  import info.magnolia.ui.contentapp.definition.ContentSubAppDescriptor;
72  import info.magnolia.ui.contentapp.definition.EditorDefinition;
73  import info.magnolia.ui.contentapp.detail.DetailLocation;
74  import info.magnolia.ui.contentapp.detail.DetailSubAppDescriptor;
75  import info.magnolia.ui.contentapp.detail.DetailView;
76  import info.magnolia.ui.framework.app.BaseSubApp;
77  import info.magnolia.ui.framework.i18n.DefaultI18NAuthoringSupport;
78  import info.magnolia.ui.vaadin.editor.PageEditorListener;
79  import info.magnolia.ui.vaadin.editor.gwt.shared.PlatformType;
80  import info.magnolia.ui.vaadin.editor.pagebar.PageBarView;
81  import info.magnolia.ui.vaadin.gwt.client.shared.AbstractElement;
82  import info.magnolia.ui.vaadin.gwt.client.shared.AreaElement;
83  import info.magnolia.ui.vaadin.gwt.client.shared.ComponentElement;
84  import info.magnolia.ui.vaadin.gwt.client.shared.PageEditorParameters;
85  import info.magnolia.ui.vaadin.gwt.client.shared.PageElement;
86  import info.magnolia.ui.vaadin.integration.contentconnector.ContentConnector;
87  import info.magnolia.ui.vaadin.integration.contentconnector.JcrContentConnector;
88  import info.magnolia.ui.vaadin.integration.jcr.JcrItemId;
89  import info.magnolia.ui.vaadin.integration.jcr.JcrItemUtil;
90  import info.magnolia.ui.vaadin.integration.jcr.JcrNodeAdapter;
91  import info.magnolia.ui.workbench.StatusBarView;
92  
93  import java.util.Arrays;
94  import java.util.List;
95  import java.util.Locale;
96  import java.util.Map;
97  
98  import javax.inject.Inject;
99  import javax.inject.Named;
100 import javax.jcr.Node;
101 import javax.jcr.RepositoryException;
102 import javax.jcr.Session;
103 
104 import org.apache.commons.lang3.StringUtils;
105 import org.slf4j.Logger;
106 import org.slf4j.LoggerFactory;
107 
108 /**
109  * PagesEditorSubApp.
110  */
111 public class PagesEditorSubApp extends BaseSubApp<PagesEditorSubAppView> implements PagesEditorSubAppView.Listener, ActionbarPresenter.Listener, PageBarView.Listener {
112 
113     private static final Logger log = LoggerFactory.getLogger(PagesEditorSubApp.class);
114 
115     protected static final String PROPERTY_TITLE = "title";
116 
117     protected static final String SECTION_PAGE = "pageActions";
118     protected static final String SECTION_PAGE_PREVIEW = "pagePreviewActions";
119     protected static final String SECTION_AREA = "areaActions";
120     protected static final String SECTION_EDITABLE_AREA = "editableAreaActions";
121     protected static final String SECTION_COMPONENT = "componentActions";
122     protected static final String SECTION_PAGE_DELETE = "pageDeleteActions";
123     protected static final String SECTION_OPTIONAL_AREA = "optionalAreaActions";
124     protected static final String SECTION_OPTIONAL_EDITABLE_AREA = "optionalEditableAreaActions";
125     protected static final String[] ALL_SECTIONS = new String[] { SECTION_AREA, SECTION_COMPONENT, SECTION_EDITABLE_AREA,
126             SECTION_OPTIONAL_AREA, SECTION_OPTIONAL_EDITABLE_AREA, SECTION_PAGE, SECTION_PAGE_DELETE, SECTION_PAGE_PREVIEW };
127 
128     private final ActionExecutor actionExecutor;
129     private final PagesEditorSubAppView view;
130     private final EventBus subAppEventBus;
131     private final EventBus admincentralEventBus;
132     private final PageEditorPresenter pageEditorPresenter;
133     private final ActionbarPresenter actionbarPresenter;
134     private final PageBarView pageBarView;
135     private final I18NAuthoringSupport i18NAuthoringSupport;
136     private final I18nContentSupport i18nContentSupport;
137     private AvailabilityChecker availabilityChecker;
138     private final StatusBarView statusBarView;
139     private final EditorDefinition editorDefinition;
140     private final String workspace;
141     private final AppContext appContext;
142     private final VersionManager versionManager;
143     private final SimpleTranslator i18n;
144 
145     private PageEditorParameters parameters;
146     private PlatformType targetPreviewPlatform = PlatformType.DESKTOP;
147     private Locale currentLocale;
148     private String caption;
149 
150     /**
151      * @deprecated since 5.2.4 - use info.magnolia.pages.app.editor.PagesEditorSubApp#PagesEditorSubApp(info.magnolia.ui.api.action.ActionExecutor, info.magnolia.ui.api.app.SubAppContext, info.magnolia.pages.app.editor.PagesEditorSubAppView, info.magnolia.event.EventBus, info.magnolia.event.EventBus, info.magnolia.pages.app.editor.PageEditorPresenter, info.magnolia.ui.actionbar.ActionbarPresenter, info.magnolia.ui.vaadin.editor.pagebar.PageBarView, info.magnolia.ui.api.i18n.I18NAuthoringSupport, info.magnolia.cms.i18n.I18nContentSupport, info.magnolia.cms.core.version.VersionManager, info.magnolia.i18nsystem.SimpleTranslator, info.magnolia.ui.api.availability.AvailabilityChecker, info.magnolia.ui.vaadin.integration.contentconnector.ContentConnector)
152      */
153     @Deprecated
154     public PagesEditorSubApp(final ActionExecutor actionExecutor, final SubAppContext subAppContext, final PagesEditorSubAppView view, @Named(AdmincentralEventBus.NAME) EventBus admincentralEventBus,
155             final @Named(SubAppEventBus.NAME) EventBus subAppEventBus, final PageEditorPresenter pageEditorPresenter, final ActionbarPresenter actionbarPresenter, final PageBarView pageBarView,
156             I18NAuthoringSupport i18NAuthoringSupport, I18nContentSupport i18nContentSupport, VersionManager versionManager, final SimpleTranslator i18n, AvailabilityChecker availabilityChecker,
157             ContentConnector contentConnector) {
158         this(actionExecutor, subAppContext, view, admincentralEventBus, subAppEventBus, pageEditorPresenter, actionbarPresenter, pageBarView, i18NAuthoringSupport, i18nContentSupport, versionManager, i18n, availabilityChecker, contentConnector, Components.getComponent(StatusBarView.class));
159     }
160 
161     @Inject
162     public PagesEditorSubApp(final ActionExecutor actionExecutor, final SubAppContext subAppContext, final PagesEditorSubAppView view, @Named(AdmincentralEventBus.NAME) EventBus admincentralEventBus,
163             final @Named(SubAppEventBus.NAME) EventBus subAppEventBus, final PageEditorPresenter pageEditorPresenter, final ActionbarPresenter actionbarPresenter, final PageBarView pageBarView,
164             I18NAuthoringSupport i18NAuthoringSupport, I18nContentSupport i18nContentSupport, VersionManager versionManager, final SimpleTranslator i18n, AvailabilityChecker availabilityChecker,
165             ContentConnector contentConnector, StatusBarView statusBarView) {
166         super(subAppContext, view);
167         this.actionExecutor = actionExecutor;
168         this.view = view;
169         this.subAppEventBus = subAppEventBus;
170         this.admincentralEventBus = admincentralEventBus;
171         this.pageEditorPresenter = pageEditorPresenter;
172         this.actionbarPresenter = actionbarPresenter;
173         this.pageBarView = pageBarView;
174         this.i18NAuthoringSupport = i18NAuthoringSupport;
175         this.i18nContentSupport = i18nContentSupport;
176         this.availabilityChecker = availabilityChecker;
177         this.statusBarView = statusBarView;
178         this.editorDefinition = ((DetailSubAppDescriptor) subAppContext.getSubAppDescriptor()).getEditor();
179         this.workspace = ((JcrContentConnector) contentConnector).getContentConnectorDefinition().getWorkspace();
180         this.appContext = subAppContext.getAppContext();
181         this.versionManager = versionManager;
182         this.i18n = i18n;
183         view.setListener(this);
184         bindHandlers();
185     }
186 
187     @Override
188     public String getCaption() {
189         return caption;
190     }
191 
192     public void updateCaption(DetailLocation location) {
193         this.caption = getPageTitle(location);
194         pageBarView.setPageName(caption, location.getNodePath());
195     }
196 
197     @Override
198     public PagesEditorSubAppView start(Location location) {
199         DetailLocation detailLocation = DetailLocation.wrap(location);
200         super.start(detailLocation);
201 
202         ActionbarDefinition actionbarDefinition = ((ContentSubAppDescriptor) getSubAppContext().getSubAppDescriptor()).getActionbar();
203         Map<String, ActionDefinition> actionDefinitions = getSubAppContext().getSubAppDescriptor().getActions();
204         actionbarPresenter.setListener(this);
205         ActionbarView actionbar = actionbarPresenter.start(actionbarDefinition, actionDefinitions);
206 
207         pageBarView.setListener(this);
208 
209         view.setActionbarView(actionbar);
210         view.setPageBarView(pageBarView);
211         view.setPageEditorView(pageEditorPresenter.start());
212         view.setStatusBarView(statusBarView);
213 
214         subAppEventBus.addHandler(ContentChangedEvent.class, new ContentChangedEvent.Handler() {
215 
216             @Override
217             public void onContentChanged(ContentChangedEvent event) {
218                 view.setStatusBarView(statusBarView);
219             }
220         });
221 
222         admincentralEventBus.addHandler(ContentChangedEvent.class, new ContentChangedEvent.Handler() {
223 
224             @Override
225             public void onContentChanged(ContentChangedEvent event) {
226                 view.setStatusBarView(statusBarView);
227             }
228         });
229 
230         admincentralEventBus.addHandler(LocationChangedEvent.class, new LocationChangedEvent.Handler() {
231             @Override
232             public void onLocationChanged(LocationChangedEvent event) {
233                 view.setStatusBarView(statusBarView);
234             }
235         });
236 
237         goToLocation(detailLocation);
238         return view;
239     }
240 
241     private void updateActions() {
242         updateActionsAccordingToOperationPermissions();
243         // actions currently always disabled
244         actionbarPresenter.disable(PageEditorListener.ACTION_CANCEL_MOVE_COMPONENT, PageEditorListener.ACTION_COPY_COMPONENT,
245                 PageEditorListener.ACTION_PASTE_COMPONENT, PageEditorListener.ACTION_UNDO, PageEditorListener.ACTION_REDO);
246     }
247 
248     /**
249      * Informs the app framework when navigating pages inside the page editor.
250      * Updates the shell fragment, caption and current location.
251      */
252     protected void updateNodePath(String path) {
253         DetailLocation detailLocation = getCurrentLocation();
254         detailLocation.updateNodePath(path);
255         setPageEditorParameters(detailLocation);
256         getAppContext().updateSubAppLocation(getSubAppContext(), detailLocation);
257         view.setStatusBarView(statusBarView); // update page status bar
258         pageEditorPresenter.updateParameters(parameters);
259     }
260 
261     /**
262      * Show/Hide actions buttons according to operation permissions.
263      */
264     private void updateActionsAccordingToOperationPermissions() {
265         AbstractElement element = pageEditorPresenter.getSelectedElement();
266 
267         if (element instanceof ComponentElement) {
268             ComponentElement componentElement = (ComponentElement) element;
269 
270             if (componentElement.getDeletable() != null && !componentElement.getDeletable()) {
271                 actionbarPresenter.disable(PageEditorListener.ACTION_DELETE_COMPONENT);
272             }
273             if (componentElement.getMoveable() != null && !componentElement.getMoveable()) {
274                 actionbarPresenter.disable(PageEditorListener.ACTION_START_MOVE_COMPONENT);
275             }
276             if (componentElement.getWritable() != null && !componentElement.getWritable()) {
277                 actionbarPresenter.disable(PageEditorListener.ACTION_EDIT_COMPONENT);
278             }
279 
280         } else if (element instanceof AreaElement) {
281             AreaElement areaElement = (AreaElement) element;
282 
283             if (areaElement.getAddible() != null && !areaElement.getAddible()) {
284                 actionbarPresenter.disable(PageEditorListener.ACTION_ADD_COMPONENT);
285             }
286         }
287     }
288 
289     @Override
290     public boolean supportsLocation(Location location) {
291         return getCurrentLocation().getNodePath().equals(DetailLocation.wrap(location).getNodePath());
292     }
293 
294     /**
295      * Wraps the current DefaultLocation in a DetailLocation. Providing getter and setters for used parameters.
296      */
297     @Override
298     public DetailLocation getCurrentLocation() {
299         return DetailLocation.wrap(super.getCurrentLocation());
300     }
301 
302     @Override
303     public void locationChanged(Location location) {
304         DetailLocation itemLocation = DetailLocation.wrap(location);
305         super.locationChanged(itemLocation);
306         goToLocation(itemLocation);
307     }
308 
309     private void goToLocation(DetailLocation location) {
310         if (isLocationChanged(location)) {
311             doGoToLocation(location);
312         }
313     }
314 
315     protected void doGoToLocation(DetailLocation location) {
316         setPageEditorParameters(location);
317         hideAllSections();
318         pageEditorPresenter.loadPageEditor(parameters);
319         updatePageBarAvailableLanguages(location);
320     }
321 
322     private void updatePageBarAvailableLanguages(DetailLocation location) {
323         try {
324             Node node = MgnlContext.getJCRSession(workspace).getNode(location.getNodePath());
325             List<Locale> locales = i18NAuthoringSupport.getAvailableLocales(node);
326             pageBarView.setAvailableLanguages(locales);
327             Locale locale = currentLocale != null && locales.contains(currentLocale) ? currentLocale : getDefaultLocale(node);
328             pageBarView.setCurrentLanguage(locale);
329         } catch (RepositoryException e) {
330             log.error("Unable to get node [{}] from workspace [{}]", location.getNodePath(), workspace, e);
331         }
332     }
333 
334     /**
335      * Returns the default locale for the given page.
336      *
337      * TODO: Once {@link DefaultI18NAuthoringSupport#getDefaultLocale(javax.jcr.Node)} is added to {@link I18NAuthoringSupport} this method should go.
338      */
339     private Locale getDefaultLocale(Node node) {
340         Locale locale;
341         if (i18NAuthoringSupport instanceof DefaultI18NAuthoringSupport) {
342             locale = ((DefaultI18NAuthoringSupport)i18NAuthoringSupport).getDefaultLocale(node);
343         } else {
344             locale = i18nContentSupport.getDefaultLocale();
345         }
346         return locale;
347     }
348 
349     private void setPageEditorParameters(DetailLocation location) {
350         DetailView.ViewType action = location.getViewType();
351         String path = location.getNodePath();
352         boolean isPreview = DetailView.ViewType.VIEW.getText().equals(action.getText());
353         this.parameters = new PageEditorParameters(MgnlContext.getContextPath(), path, isPreview);
354         this.parameters.setPlatformType(targetPreviewPlatform);
355         try {
356             Node node = MgnlContext.getJCRSession(workspace).getNode(path);
357             String uri = i18NAuthoringSupport.createI18NURI(node, currentLocale);
358             StringBuffer sb = new StringBuffer(uri);
359 
360             if (isPreview) {
361                 LinkUtil.addParameter(sb, "mgnlPreview", Boolean.toString(true));
362             } else {
363                 // reset channel
364                 this.targetPreviewPlatform = PlatformType.DESKTOP;
365                 this.parameters.setPlatformType(targetPreviewPlatform);
366                 pageBarView.setPlatFormType(targetPreviewPlatform);
367 
368                 LinkUtil.addParameter(sb, "mgnlPreview", Boolean.toString(false));
369             }
370             LinkUtil.addParameter(sb, "mgnlChannel", targetPreviewPlatform.getId());
371 
372             if (location.hasVersion()) {
373                 LinkUtil.addParameter(sb, "mgnlVersion", location.getVersion());
374             }
375             uri = sb.toString();
376             this.parameters.setUrl(uri);
377             updateCaption(location);
378             pageBarView.togglePreviewMode(isPreview);
379         } catch (RepositoryException e) {
380             log.error(e.getMessage(), e);
381         }
382     }
383 
384     private boolean isLocationChanged(DetailLocation location) {
385         DetailView.ViewType action = location.getViewType();
386         String path = location.getNodePath();
387 
388         if (parameters != null && (parameters.getNodePath().equals(path) && parameters.isPreview() == DetailView.ViewType.VIEW.getText().equals(action.getText())) && !location.hasVersion()) {
389             return false;
390         }
391         return true;
392     }
393 
394     private String getPageTitle(DetailLocation location) {
395         String caption = StringUtils.EMPTY;
396         try {
397             Session session = MgnlContext.getJCRSession(workspace);
398             Node node = session.getNode(location.getNodePath());
399             if (StringUtils.isNotBlank(location.getVersion())) {
400                 node = versionManager.getVersion(node, location.getVersion());
401                 caption = i18n.translate("subapp.versioned_page", PropertyUtil.getString(node, PROPERTY_TITLE, node.getName()), location.getVersion());
402             } else {
403                 caption = PropertyUtil.getString(node, PROPERTY_TITLE, node.getName());
404             }
405 
406         } catch (RepositoryException e) {
407             log.warn("Could not set page Tab Title for item : {}", location.getNodePath(), e);
408         }
409         return caption;
410     }
411 
412     private void hideAllSections() {
413         actionbarPresenter.hideSection(ALL_SECTIONS);
414     }
415 
416     private void bindHandlers() {
417 
418         admincentralEventBus.addHandler(ContentChangedEvent.class, new ContentChangedEvent.Handler() {
419 
420             @Override
421             public void onContentChanged(ContentChangedEvent event) {
422                 JcrItemId itemId = (JcrItemId) event.getItemId();
423                 if (itemId.getWorkspace().equals(RepositoryConstants.WEBSITE)) {
424                     // Check if the node still exist
425                     try {
426                         String currentNodePath = getCurrentLocation().getNodePath();
427                         if (!MgnlContext.getJCRSession(RepositoryConstants.WEBSITE).nodeExists(currentNodePath)) {
428                             getSubAppContext().close();
429                         }
430                     } catch (RepositoryException e) {
431                         log.warn("Could not determine if currently edited page exists", e);
432                     }
433                 }
434             }
435         });
436 
437         subAppEventBus.addHandler(ComponentMoveEvent.class, new ComponentMoveEvent.Handler() {
438             @Override
439             public void onMove(ComponentMoveEvent event) {
440                 if (event.isStart()) {
441                     actionbarPresenter.disable(PageEditorListener.ACTION_START_MOVE_COMPONENT);
442                     actionbarPresenter.enable(PageEditorListener.ACTION_CANCEL_MOVE_COMPONENT);
443                 } else {
444                     actionbarPresenter.enable(PageEditorListener.ACTION_START_MOVE_COMPONENT);
445                     actionbarPresenter.disable(PageEditorListener.ACTION_CANCEL_MOVE_COMPONENT);
446                 }
447             }
448         });
449 
450         subAppEventBus.addHandler(NodeSelectedEvent.class, new NodeSelectedEvent.Handler() {
451 
452             @Override
453             public void onItemSelected(NodeSelectedEvent event) {
454                 AbstractElement element = event.getElement();
455                 updateActionbar(element);
456             }
457         });
458     }
459 
460     @Override
461     public void onActionbarItemClicked(String actionName) {
462         prepareAndExecutePagesEditorAction(actionName);
463     }
464 
465     protected void prepareAndExecutePagesEditorAction(String actionName) {
466         AbstractElement selectedElement = pageEditorPresenter.getSelectedElement();
467         try {
468             Session session = MgnlContext.getJCRSession(workspace);
469             final javax.jcr.Item item = session.getItem(selectedElement.getPath());
470             actionExecutor.execute(actionName, new JcrNodeAdapter((Node) item), selectedElement, pageEditorPresenter);
471 
472         } catch (RepositoryException e) {
473             Message error = new Message(MessageType.ERROR, i18n.translate("pages.pagesEditorSubapp.actionExecutionException.message"), e.getMessage());
474             log.error("An error occurred while executing action [{}]", actionName, e);
475             appContext.sendLocalMessage(error);
476         } catch (ActionExecutionException e) {
477             Message error = new Message(MessageType.ERROR, i18n.translate("pages.pagesEditorSubapp.actionExecutionException.message"), e.getMessage());
478             log.error("An error occurred while executing action [{}]", actionName, e);
479             appContext.sendLocalMessage(error);
480         }
481     }
482 
483     @Override
484     public void languageSelected(Locale locale) {
485         if (locale != null && !locale.equals(currentLocale)) {
486             this.currentLocale = locale;
487             if (i18NAuthoringSupport instanceof DefaultI18NAuthoringSupport) {
488                 ((DefaultI18NAuthoringSupport) i18NAuthoringSupport).setAuthorLocale(locale);
489             }
490             doGoToLocation(getCurrentLocation());
491         }
492     }
493 
494     @Override
495     public void platformSelected(PlatformType platformType) {
496         if (platformType != null && !platformType.equals(targetPreviewPlatform)) {
497             this.targetPreviewPlatform = platformType;
498             doGoToLocation(getCurrentLocation());
499         }
500     }
501 
502     /**
503      * This method has package visibility for testing purposes only.
504      */
505     final PageEditorParameters getParameters() {
506         return parameters;
507     }
508 
509     private boolean isDeletedNode(String workspace, String path) {
510         Node node = SessionUtil.getNode(workspace, path);
511         try {
512             if (node != null) {
513                 return NodeUtil.hasMixin(node, NodeTypes.Deleted.NAME);
514             } else {
515                 return false;
516             }
517         } catch (RepositoryException re) {
518             log.warn("Not able to check if node has MixIn");
519             return false;
520         }
521     }
522 
523     private void updateActionbar(final AbstractElement element) {
524         String path = element.getPath();
525         String dialog = element.getDialog();
526         if (StringUtils.isEmpty(path)) {
527             path = "/";
528         }
529         hideAllSections();
530 
531         if (isDeletedNode(workspace, path)) {
532             actionbarPresenter.showSection(SECTION_PAGE_DELETE);
533 
534             if (!getCurrentLocation().hasVersion()) {
535                 actionbarPresenter.enable("showPreviousVersion");
536             } else {
537                 actionbarPresenter.disable("showPreviousVersion");
538             }
539             actionbarPresenter.enable("restorePreviousVersion");
540             actionbarPresenter.enable("activateDelete");
541 
542         } else {
543 
544             ActionbarSectionDefinition def;
545             String sectionName = null;
546 
547             if (element instanceof PageElement) {
548 
549                 if (!path.equals(parameters.getNodePath())) {
550                     updateNodePath(path);
551                 }
552 
553                 if (parameters.isPreview()) {
554                     sectionName = SECTION_PAGE_PREVIEW;
555                 } else {
556                     sectionName = SECTION_PAGE;
557                 }
558 
559             } else if (element instanceof AreaElement) {
560                 if (dialog == null) {
561                     sectionName = SECTION_AREA;
562                 } else {
563                     sectionName = SECTION_EDITABLE_AREA;
564                 }
565 
566             } else if (element instanceof ComponentElement) {
567                 sectionName = SECTION_COMPONENT;
568             }
569 
570             if (sectionName != null) {
571                 actionbarPresenter.showSection(sectionName);
572                 def = getActionbarSectionDefinitionByName(sectionName);
573                 enableOrDisableActions(def, path);
574             }
575             updateActions();
576         }
577     }
578 
579     private void enableOrDisableActions(final ActionbarSectionDefinition def, final String path) {
580         if (def == null) {
581             return;
582         }
583         // Evaluate availability of each action within the section
584         Node node = SessionUtil.getNode(workspace, path);
585         for (ActionbarGroupDefinition groupDefinition : def.getGroups()) {
586             for (ActionbarItemDefinition itemDefinition : groupDefinition.getItems()) {
587 
588                 String actionName = itemDefinition.getName();
589                 AvailabilityDefinition availabilityDefinition = actionExecutor.getActionDefinition(actionName).getAvailability();
590                 try {
591                     Object itemId = JcrItemUtil.getItemId(node);
592                     if (availabilityChecker.isAvailable(availabilityDefinition, Arrays.asList(itemId))) {
593                         actionbarPresenter.enable(actionName);
594                     } else {
595                         actionbarPresenter.disable(actionName);
596                     }
597                 } catch (RepositoryException e) {
598                     log.error("Failed to update action availability: " + e.getMessage(), e);
599                 }
600             }
601         }
602     }
603 
604     private ActionbarSectionDefinition getActionbarSectionDefinitionByName(final String sectionName) {
605         ActionbarDefinition actionbarDefinition = ((DetailSubAppDescriptor) getSubAppContext().getSubAppDescriptor()).getActionbar();
606         if (actionbarDefinition == null) {
607             log.warn("No actionbar definition found, returning null");
608             return null;
609         }
610 
611         for (ActionbarSectionDefinition section : actionbarDefinition.getSections()) {
612             if (section.getName().equals(sectionName)) {
613                 return section;
614             }
615         }
616         log.warn("No section named [{}] found, returning null", sectionName);
617         return null;
618     }
619 
620     @Override
621     public void onEscape() {
622         if (pageEditorPresenter.isMoving()) {
623             pageEditorPresenter.onAction(PageEditorListener.ACTION_CANCEL_MOVE_COMPONENT);
624         } else {
625             // Toggle preview and edit mode.
626             if (getCurrentLocation().getViewType().equals(DetailView.ViewType.EDIT)) {
627                 prepareAndExecutePagesEditorAction(PageEditorListener.ACTION_VIEW_PREVIEW);
628             } else {
629                 prepareAndExecutePagesEditorAction(PageEditorListener.ACTION_VIEW_EDIT);
630             }
631         }
632     }
633 
634     protected String getWorkspace() {
635         return workspace;
636     }
637 
638 }