View Javadoc
1   /**
2    * This file Copyright (c) 2013-2015 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.Path;
37  import info.magnolia.cms.core.version.VersionManager;
38  import info.magnolia.cms.i18n.I18nContentSupport;
39  import info.magnolia.context.MgnlContext;
40  import info.magnolia.event.EventBus;
41  import info.magnolia.i18nsystem.SimpleTranslator;
42  import info.magnolia.jcr.util.NodeTypes;
43  import info.magnolia.jcr.util.PropertyUtil;
44  import info.magnolia.link.LinkUtil;
45  import info.magnolia.objectfactory.Components;
46  import info.magnolia.pages.app.editor.event.NodeSelectedEvent;
47  import info.magnolia.repository.RepositoryConstants;
48  import info.magnolia.ui.actionbar.ActionbarPresenter;
49  import info.magnolia.ui.actionbar.ActionbarView;
50  import info.magnolia.ui.actionbar.definition.ActionbarDefinition;
51  import info.magnolia.ui.actionbar.definition.ActionbarGroupDefinition;
52  import info.magnolia.ui.actionbar.definition.ActionbarItemDefinition;
53  import info.magnolia.ui.actionbar.definition.ActionbarSectionDefinition;
54  import info.magnolia.ui.api.action.ActionDefinition;
55  import info.magnolia.ui.api.action.ActionExecutionException;
56  import info.magnolia.ui.api.action.ActionExecutor;
57  import info.magnolia.ui.api.app.AppContext;
58  import info.magnolia.ui.api.app.SubAppContext;
59  import info.magnolia.ui.api.app.SubAppEventBus;
60  import info.magnolia.ui.api.availability.AvailabilityChecker;
61  import info.magnolia.ui.api.availability.AvailabilityDefinition;
62  import info.magnolia.ui.api.event.AdmincentralEventBus;
63  import info.magnolia.ui.api.event.ContentChangedEvent;
64  import info.magnolia.ui.api.i18n.I18NAuthoringSupport;
65  import info.magnolia.ui.api.location.Location;
66  import info.magnolia.ui.api.location.LocationChangedEvent;
67  import info.magnolia.ui.api.message.Message;
68  import info.magnolia.ui.api.message.MessageType;
69  import info.magnolia.ui.contentapp.definition.ContentSubAppDescriptor;
70  import info.magnolia.ui.contentapp.detail.DetailLocation;
71  import info.magnolia.ui.contentapp.detail.DetailSubAppDescriptor;
72  import info.magnolia.ui.contentapp.detail.DetailView;
73  import info.magnolia.ui.framework.app.BaseSubApp;
74  import info.magnolia.ui.framework.app.SubAppContextImpl;
75  import info.magnolia.ui.framework.i18n.DefaultI18NAuthoringSupport;
76  import info.magnolia.ui.vaadin.editor.PageEditorListener;
77  import info.magnolia.ui.vaadin.editor.gwt.shared.PlatformType;
78  import info.magnolia.ui.vaadin.editor.pagebar.PageBarView;
79  import info.magnolia.ui.vaadin.gwt.client.shared.AbstractElement;
80  import info.magnolia.ui.vaadin.gwt.client.shared.AreaElement;
81  import info.magnolia.ui.vaadin.gwt.client.shared.PageEditorParameters;
82  import info.magnolia.ui.vaadin.gwt.client.shared.PageElement;
83  import info.magnolia.ui.vaadin.integration.contentconnector.ContentConnector;
84  import info.magnolia.ui.vaadin.integration.contentconnector.JcrContentConnector;
85  import info.magnolia.ui.vaadin.integration.jcr.JcrNewNodeItemId;
86  import info.magnolia.ui.workbench.StatusBarView;
87  
88  import java.util.Arrays;
89  import java.util.List;
90  import java.util.Locale;
91  import java.util.Map;
92  
93  import javax.inject.Inject;
94  import javax.inject.Named;
95  import javax.jcr.Node;
96  import javax.jcr.RepositoryException;
97  import javax.jcr.Session;
98  
99  import org.apache.commons.lang3.ObjectUtils;
100 import org.apache.commons.lang3.StringUtils;
101 import org.slf4j.Logger;
102 import org.slf4j.LoggerFactory;
103 
104 /**
105  * PagesEditorSubApp.
106  */
107 public class PagesEditorSubApp extends BaseSubApp<PagesEditorSubAppView> implements PagesEditorSubAppView.Listener, ActionbarPresenter.Listener, PageBarView.Listener, PageEditorPresenter.Listener {
108 
109     private static final Logger log = LoggerFactory.getLogger(PagesEditorSubApp.class);
110 
111     protected static final String PROPERTY_TITLE = "title";
112 
113     private final ActionExecutor actionExecutor;
114     private final SubAppContext subAppContext;
115     private final PagesEditorSubAppView view;
116     private final EventBus subAppEventBus;
117     private final EventBus admincentralEventBus;
118     private final PageEditorPresenter pageEditorPresenter;
119     private final ActionbarPresenter actionbarPresenter;
120     private final PageBarView pageBarView;
121     private final I18NAuthoringSupport i18NAuthoringSupport;
122     private final I18nContentSupport i18nContentSupport;
123     private final JcrContentConnector contentConnector;
124     private final AvailabilityChecker availabilityChecker;
125     private final StatusBarView statusBarView;
126     private final String workspace;
127     private final AppContext appContext;
128     private final VersionManager versionManager;
129     private final SimpleTranslator i18n;
130 
131     private PageEditorParameters parameters;
132     private PlatformType targetPreviewPlatform = PlatformType.DESKTOP;
133     private Locale currentLocale;
134     private String caption;
135 
136     @Inject
137     public PagesEditorSubApp(final ActionExecutor actionExecutor, final SubAppContext subAppContext, final PagesEditorSubAppView view, @Named(AdmincentralEventBus.NAME) EventBus admincentralEventBus,
138                              final @Named(SubAppEventBus.NAME) EventBus subAppEventBus, final PageEditorPresenter pageEditorPresenter, final ActionbarPresenter actionbarPresenter, final PageBarView pageBarView,
139                              I18NAuthoringSupport i18NAuthoringSupport, I18nContentSupport i18nContentSupport, VersionManager versionManager, final SimpleTranslator i18n, AvailabilityChecker availabilityChecker,
140                              ContentConnector contentConnector, StatusBarView statusBarView) {
141         super(subAppContext, view);
142         this.actionExecutor = actionExecutor;
143         this.subAppContext = subAppContext;
144         this.view = view;
145         this.subAppEventBus = subAppEventBus;
146         this.admincentralEventBus = admincentralEventBus;
147         this.pageEditorPresenter = pageEditorPresenter;
148         this.actionbarPresenter = actionbarPresenter;
149         this.pageBarView = pageBarView;
150         this.i18NAuthoringSupport = i18NAuthoringSupport;
151         this.i18nContentSupport = i18nContentSupport;
152         this.availabilityChecker = availabilityChecker;
153         this.statusBarView = statusBarView;
154         this.contentConnector = (JcrContentConnector) contentConnector;
155         this.workspace = this.contentConnector.getContentConnectorDefinition().getWorkspace();
156         this.appContext = subAppContext.getAppContext();
157         this.versionManager = versionManager;
158         this.i18n = i18n;
159         bindHandlers();
160     }
161 
162     /**
163      * @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)
164      */
165     @Deprecated
166     public PagesEditorSubApp(final ActionExecutor actionExecutor, final SubAppContext subAppContext, final PagesEditorSubAppView view, @Named(AdmincentralEventBus.NAME) EventBus admincentralEventBus,
167                              final @Named(SubAppEventBus.NAME) EventBus subAppEventBus, final PageEditorPresenter pageEditorPresenter, final ActionbarPresenter actionbarPresenter, final PageBarView pageBarView,
168                              I18NAuthoringSupport i18NAuthoringSupport, I18nContentSupport i18nContentSupport, VersionManager versionManager, final SimpleTranslator i18n, AvailabilityChecker availabilityChecker,
169                              ContentConnector contentConnector) {
170         this(actionExecutor, subAppContext, view, admincentralEventBus, subAppEventBus, pageEditorPresenter, actionbarPresenter, pageBarView, i18NAuthoringSupport, i18nContentSupport, versionManager, i18n, availabilityChecker, contentConnector, Components.getComponent(StatusBarView.class));
171     }
172 
173     @Override
174     public String getCaption() {
175         return caption;
176     }
177 
178     public void updateCaption(DetailLocation location) {
179         this.caption = getPageTitle(location);
180         pageBarView.setPageName(caption, location.getNodePath());
181     }
182 
183     @Override
184     public PagesEditorSubAppView start(Location location) {
185         view.setListener(this);
186 
187         DetailLocation detailLocation = DetailLocation.wrap(location);
188         super.start(detailLocation);
189 
190         ActionbarDefinition actionbarDefinition = ((ContentSubAppDescriptor) getSubAppContext().getSubAppDescriptor()).getActionbar();
191         Map<String, ActionDefinition> actionDefinitions = getSubAppContext().getSubAppDescriptor().getActions();
192         actionbarPresenter.setListener(this);
193         ActionbarView actionbar = actionbarPresenter.start(actionbarDefinition, actionDefinitions);
194 
195         pageBarView.setListener(this);
196         pageEditorPresenter.setListener(this);
197 
198         view.setActionbarView(actionbar);
199         view.setPageBarView(pageBarView);
200         view.setPageEditorView(pageEditorPresenter.start());
201         view.setStatusBarView(statusBarView);
202 
203         goToLocation(detailLocation);
204         return view;
205     }
206 
207     /**
208      * Informs the app framework when navigating pages inside the page editor.
209      * Updates the shell fragment, caption and current location.
210      */
211     protected void updateNodePath(String path) {
212         DetailLocation detailLocation = getCurrentLocation();
213         detailLocation.updateNodePath(path);
214         setPageEditorParameters(detailLocation);
215         getAppContext().updateSubAppLocation(getSubAppContext(), detailLocation);
216         view.setStatusBarView(statusBarView); // update page status bar
217         pageEditorPresenter.updateParameters(parameters);
218     }
219 
220     @Override
221     public boolean supportsLocation(Location location) {
222         return getCurrentLocation().getNodePath().equals(DetailLocation.wrap(location).getNodePath());
223     }
224 
225     /**
226      * Wraps the current DefaultLocation in a DetailLocation. Providing getter and setters for used parameters.
227      */
228     @Override
229     public DetailLocation getCurrentLocation() {
230         return DetailLocation.wrap(super.getCurrentLocation());
231     }
232 
233     @Override
234     public void locationChanged(Location location) {
235         DetailLocation itemLocation = DetailLocation.wrap(location);
236         super.locationChanged(itemLocation);
237         goToLocation(itemLocation);
238     }
239 
240     private void goToLocation(DetailLocation location) {
241         if (isLocationChanged(location)) {
242             doGoToLocation(location);
243         }
244     }
245 
246     protected void doGoToLocation(DetailLocation location) {
247         setPageEditorParameters(location);
248         updateActionbar();
249         pageEditorPresenter.loadPageEditor(parameters);
250         updatePageBarAvailableLanguages(location);
251     }
252 
253     private void updatePageBarAvailableLanguages(DetailLocation location) {
254         try {
255             Node node = MgnlContext.getJCRSession(workspace).getNode(location.getNodePath());
256             List<Locale> locales = i18NAuthoringSupport.getAvailableLocales(node);
257             pageBarView.setAvailableLanguages(locales);
258             Locale locale = currentLocale != null && locales.contains(currentLocale) ? currentLocale : getDefaultLocale(node);
259             pageBarView.setCurrentLanguage(locale);
260         } catch (RepositoryException e) {
261             log.error("Unable to get node [{}] from workspace [{}]", location.getNodePath(), workspace, e);
262         }
263     }
264 
265     /**
266      * Returns the default locale for the given page.
267      *
268      * TODO: Once {@link DefaultI18NAuthoringSupport#getDefaultLocale(javax.jcr.Node)} is added to {@link I18NAuthoringSupport} this method should go.
269      */
270     private Locale getDefaultLocale(Node node) {
271         Locale locale;
272         if (i18NAuthoringSupport instanceof DefaultI18NAuthoringSupport) {
273             locale = ((DefaultI18NAuthoringSupport)i18NAuthoringSupport).getDefaultLocale(node);
274         } else {
275             locale = i18nContentSupport.getDefaultLocale();
276         }
277         return locale;
278     }
279 
280     private void setPageEditorParameters(DetailLocation location) {
281         DetailView.ViewType action = location.getViewType();
282         String path = location.getNodePath();
283         boolean isPreview = DetailView.ViewType.VIEW.getText().equals(action.getText());
284         this.parameters = new PageEditorParameters(MgnlContext.getContextPath(), path, isPreview);
285         this.parameters.setPlatformType(targetPreviewPlatform);
286         try {
287             Node node = MgnlContext.getJCRSession(workspace).getNode(path);
288             String uri = i18NAuthoringSupport.createI18NURI(node, currentLocale);
289             StringBuffer sb = new StringBuffer(uri);
290 
291             if (isPreview) {
292                 LinkUtil.addParameter(sb, "mgnlPreview", Boolean.toString(true));
293             } else {
294                 // reset channel
295                 this.targetPreviewPlatform = PlatformType.DESKTOP;
296                 this.parameters.setPlatformType(targetPreviewPlatform);
297                 pageBarView.setPlatFormType(targetPreviewPlatform);
298 
299                 LinkUtil.addParameter(sb, "mgnlPreview", Boolean.toString(false));
300             }
301             LinkUtil.addParameter(sb, "mgnlChannel", targetPreviewPlatform.getId());
302 
303             if (location.hasVersion()) {
304                 LinkUtil.addParameter(sb, "mgnlVersion", location.getVersion());
305             }
306             uri = sb.toString();
307             this.parameters.setUrl(uri);
308             updateCaption(location);
309             pageBarView.togglePreviewMode(isPreview);
310         } catch (RepositoryException e) {
311             log.error(e.getMessage(), e);
312         }
313     }
314 
315     private boolean isLocationChanged(DetailLocation location) {
316         DetailView.ViewType action = location.getViewType();
317         String path = location.getNodePath();
318 
319         if (parameters != null && (parameters.getNodePath().equals(path) && parameters.isPreview() == DetailView.ViewType.VIEW.getText().equals(action.getText())) && !location.hasVersion()) {
320             return false;
321         }
322         return true;
323     }
324 
325     private String getPageTitle(DetailLocation location) {
326         String caption = StringUtils.EMPTY;
327         try {
328             Session session = MgnlContext.getJCRSession(workspace);
329             Node node = session.getNode(location.getNodePath());
330             if (StringUtils.isNotBlank(location.getVersion())) {
331                 node = versionManager.getVersion(node, location.getVersion());
332                 caption = i18n.translate("subapp.versioned_page", PropertyUtil.getString(node, PROPERTY_TITLE, node.getName()), location.getVersion());
333             } else {
334                 caption = PropertyUtil.getString(node, PROPERTY_TITLE, node.getName());
335             }
336 
337         } catch (RepositoryException e) {
338             log.warn("Could not set page Tab Title for item : {}", location.getNodePath(), e);
339         }
340         return caption;
341     }
342 
343     private void bindHandlers() {
344 
345         admincentralEventBus.addHandler(ContentChangedEvent.class, new ContentChangedEvent.Handler() {
346 
347             @Override
348             public void onContentChanged(ContentChangedEvent event) {
349                 if (contentConnector.canHandleItem(event.getItemId())) {
350                     // Check if the node still exist
351                     try {
352                         String currentNodePath = getCurrentLocation().getNodePath();
353                         if (!MgnlContext.getJCRSession(RepositoryConstants.WEBSITE).nodeExists(currentNodePath)) {
354                             getSubAppContext().close();
355                         }
356                     } catch (RepositoryException e) {
357                         log.warn("Could not determine if currently edited page exists", e);
358                     }
359                 }
360             }
361         });
362 
363         subAppEventBus.addHandler(NodeSelectedEvent.class, new NodeSelectedEvent.Handler() {
364 
365             @Override
366             public void onItemSelected(NodeSelectedEvent event) {
367                 AbstractElement element = event.getElement();
368                 if (element instanceof PageElement) {
369                     String path = element.getPath();
370                     if (StringUtils.isEmpty(path)) {
371                         path = "/";
372                     }
373                     if (!path.equals(parameters.getNodePath())) {
374                         updateNodePath(path);
375                     }
376                 }
377                 updateActionbar();
378             }
379         });
380 
381         subAppEventBus.addHandler(ContentChangedEvent.class, new ContentChangedEvent.Handler() {
382 
383             @Override
384             public void onContentChanged(ContentChangedEvent event) {
385                 updatePageEditor();
386             }
387         });
388 
389         admincentralEventBus.addHandler(ContentChangedEvent.class, new ContentChangedEvent.Handler() {
390 
391             @Override
392             public void onContentChanged(ContentChangedEvent event) {
393                 updatePageEditor();
394             }
395         });
396 
397         admincentralEventBus.addHandler(LocationChangedEvent.class, new LocationChangedEvent.Handler() {
398             @Override
399             public void onLocationChanged(LocationChangedEvent event) {
400                 view.setStatusBarView(statusBarView);
401             }
402         });
403     }
404 
405     private void updatePageEditor() {
406         // Temporarily only in SubAppContextImpl, by the time method is generalized to {@link SubAppContext} interface in 5.4.
407         if (subAppContext instanceof SubAppContextImpl) {
408             Locale authoringLocale = ((SubAppContextImpl) subAppContext).getAuthoringLocale();
409             if (!ObjectUtils.equals(authoringLocale, currentLocale)) {
410                 // authoring locale has changed, make sure to update page-editor
411                 currentLocale = authoringLocale;
412                 doGoToLocation(getCurrentLocation());
413             } else {
414                 // authoring locale hasn't changed, simply refresh page-editor
415                 pageEditorPresenter.refresh();
416             }
417         } else {
418             // authoring locale hasn't changed, simply refresh page-editor
419             pageEditorPresenter.refresh();
420         }
421         view.setStatusBarView(statusBarView);
422     }
423 
424     @Override
425     public void onActionbarItemClicked(String actionName) {
426         prepareAndExecutePagesEditorAction(actionName);
427     }
428 
429     protected void prepareAndExecutePagesEditorAction(String actionName) {
430         AbstractElement selectedElement = pageEditorPresenter.getSelectedElement();
431         if (selectedElement == null) {
432             log.warn("Trying to execute action [{}] but no element was selected. Was the page actually loaded?", actionName);
433             return;
434         }
435         try {
436             Object itemId = getItemId(selectedElement);
437             actionExecutor.execute(actionName, contentConnector.getItem(itemId), selectedElement, pageEditorPresenter);
438         } catch (ActionExecutionException e) {
439             Message error = new Message(MessageType.ERROR, i18n.translate("pages.pagesEditorSubapp.actionExecutionException.message"), e.getMessage());
440             log.error("An error occurred while executing action [{}]", actionName, e);
441             appContext.sendLocalMessage(error);
442         }
443     }
444 
445     @Override
446     public void languageSelected(Locale locale) {
447         if (locale != null && !locale.equals(currentLocale)) {
448             this.currentLocale = locale;
449             // Temporarily only in SubAppContextImpl, by the time method is generalized to {@link SubAppContext} interface in 5.4.
450             if (subAppContext instanceof SubAppContextImpl) {
451                 ((SubAppContextImpl) subAppContext).setAuthoringLocale(locale);
452             }
453             doGoToLocation(getCurrentLocation());
454         }
455     }
456 
457     @Override
458     public void platformSelected(PlatformType platformType) {
459         if (platformType != null && !platformType.equals(targetPreviewPlatform)) {
460             this.targetPreviewPlatform = platformType;
461             doGoToLocation(getCurrentLocation());
462         }
463     }
464 
465     /**
466      * This method has package visibility for testing purposes only.
467      */
468     public PageEditorParameters getParameters() {
469         return parameters;
470     }
471 
472     public void updateActionbar() {
473         Object itemId = getItemId(pageEditorPresenter.getSelectedElement());
474 
475         DetailSubAppDescriptor subAppDescriptor = (DetailSubAppDescriptor) getSubAppContext().getSubAppDescriptor();
476         ActionbarDefinition actionbarDefinition = subAppDescriptor.getActionbar();
477         if (actionbarDefinition == null) {
478             return;
479         }
480         List<ActionbarSectionDefinition> sections = actionbarDefinition.getSections();
481         // Figure out which section to show, only one
482         ActionbarSectionDefinition sectionDefinition = getVisibleSection(sections, itemId);
483 
484         // Hide all other sections
485         for (ActionbarSectionDefinition section : sections) {
486             actionbarPresenter.hideSection(section.getName());
487         }
488 
489         if (sectionDefinition != null) {
490             // Show our section
491             actionbarPresenter.showSection(sectionDefinition.getName());
492 
493             // Evaluate availability of each action within the section
494             for (ActionbarGroupDefinition groupDefinition : sectionDefinition.getGroups()) {
495                 for (ActionbarItemDefinition itemDefinition : groupDefinition.getItems()) {
496 
497                     String actionName = itemDefinition.getName();
498                     ActionDefinition actionDefinition = actionExecutor.getActionDefinition(actionName);
499                     if (actionDefinition != null) {
500                         AvailabilityDefinition availability = actionDefinition.getAvailability();
501                         if (availabilityChecker.isAvailable(availability, Arrays.asList(itemId))) {
502                             actionbarPresenter.enable(actionName);
503                         } else {
504                             actionbarPresenter.disable(actionName);
505                         }
506                     }
507                 }
508             }
509         }
510     }
511 
512     private Object getItemId(AbstractElement element) {
513         if (element == null) {
514             return null;
515         }
516         else if (element instanceof AreaElement && ((AreaElement) element).isOptional() && !((AreaElement) element).isCreated()) {
517 
518             try {
519                 int index = element.getPath().lastIndexOf("/");
520                 String parentPath = element.getPath().substring(0, index);
521                 String relPath = element.getPath().substring(index + 1);
522 
523                 Node parent = MgnlContext.getJCRSession(getWorkspace()).getNode(parentPath);
524 
525                 JcrNewNodeItemId jcrNewNodeItemId = new JcrNewNodeItemId(parent.getIdentifier(), getWorkspace(), NodeTypes.Area.NAME);
526                 jcrNewNodeItemId.setName(Path.getUniqueLabel(parent, relPath));
527                 return jcrNewNodeItemId;
528             } catch (RepositoryException e) {
529                 log.error("Failed to create new jcr node item id: " + e.getMessage(), e);
530             }
531             return null;
532         }
533         else {
534             return contentConnector.getItemIdByUrlFragment(element.getPath());
535         }
536     }
537 
538     private ActionbarSectionDefinition getVisibleSection(List<ActionbarSectionDefinition> sections, Object itemId) {
539         for (ActionbarSectionDefinition section : sections) {
540             if (availabilityChecker.isAvailable(section.getAvailability(), Arrays.asList(itemId)))
541                 return section;
542         }
543         return null;
544     }
545 
546     @Override
547     public void onEscape() {
548         if (pageEditorPresenter.isMoving()) {
549             pageEditorPresenter.onAction(PageEditorListener.ACTION_CANCEL_MOVE_COMPONENT);
550         } else {
551             // Toggle preview and edit mode.
552             if (getCurrentLocation().getViewType().equals(DetailView.ViewType.EDIT)) {
553                 prepareAndExecutePagesEditorAction(PageEditorListener.ACTION_VIEW_PREVIEW);
554             } else {
555                 prepareAndExecutePagesEditorAction(PageEditorListener.ACTION_VIEW_EDIT);
556             }
557         }
558     }
559 
560     protected String getWorkspace() {
561         return workspace;
562     }
563 
564     public PageEditorPresenter getPageEditorPresenter() {
565         return pageEditorPresenter;
566     }
567 
568     @Override
569     public void onMove() {
570         updateActionbar();
571     }
572 }