View Javadoc
1   /**
2    * This file Copyright (c) 2012-2018 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.ui.contentapp.detail;
35  
36  import info.magnolia.event.EventBus;
37  import info.magnolia.i18nsystem.SimpleTranslator;
38  import info.magnolia.ui.api.app.SubAppContext;
39  import info.magnolia.ui.api.event.AdmincentralEventBus;
40  import info.magnolia.ui.api.event.ContentChangedEvent;
41  import info.magnolia.ui.api.location.Location;
42  import info.magnolia.ui.api.view.View;
43  import info.magnolia.ui.contentapp.ContentSubAppView;
44  import info.magnolia.ui.framework.app.BaseSubApp;
45  import info.magnolia.ui.vaadin.integration.contentconnector.ContentConnector;
46  import info.magnolia.ui.vaadin.integration.jcr.JcrNewNodeItemId;
47  
48  import javax.inject.Inject;
49  import javax.inject.Named;
50  
51  import org.apache.commons.lang3.StringUtils;
52  import org.slf4j.Logger;
53  import org.slf4j.LoggerFactory;
54  
55  /**
56   * Base implementation of an item subApp. Provides sensible implementation for
57   * services shared by all item subApps. Implementers of this class represent a
58   * tab for viewing and editing items typically opened from an {@link info.magnolia.ui.contentapp.browser.BrowserSubApp}. Subclasses can
59   * augment the default behavior and perform additional tasks by overriding the
60   * following methods:
61   * <ul>
62   * <li>{@link #onSubAppStart()}
63   * <li>{@link #locationChanged(Location)}
64   * </ul>
65   * Currently lacking listeners for {@link info.magnolia.ui.api.event.ContentChangedEvent}. Currently
66   * lacking handling of locationChanged. Related to MGNLUI-154
67   *
68   * @see DetailEditorPresenter
69   * @see info.magnolia.ui.contentapp.ContentSubAppView
70   * @see DetailLocation
71   *
72   * @deprecated since 6.2 - use {@link info.magnolia.ui.contentapp.detail.ContentDetailSubApp} instead.
73   *
74   * @see <a href="https://documentation.magnolia-cms.com/display/DOCS62/Upgrading+to+Magnolia+6.2.x">Upgrading to Magnolia 6.2.x</a>
75   */
76  @Deprecated
77  public class DetailSubApp extends BaseSubApp<ContentSubAppView> {
78  
79      private static final Logger log = LoggerFactory.getLogger(DetailSubApp.class);
80  
81      private final DetailEditorPresenter presenter;
82      private final EventBus adminCentralEventBus;
83      private final SimpleTranslator i18n;
84  
85      private Object itemId;
86  
87      private String caption;
88  
89      private ContentConnector contentConnector;
90  
91      @Inject
92      protected DetailSubApp(final SubAppContext subAppContext, final ContentSubAppView view, @Named(AdmincentralEventBus.NAME) EventBus adminCentralEventBus,
93              DetailEditorPresenter presenter, SimpleTranslator i18n, ContentConnector contentConnector) {
94          super(subAppContext, view);
95  
96          this.adminCentralEventBus = adminCentralEventBus;
97          this.presenter = presenter;
98          this.i18n = i18n;
99          this.contentConnector = contentConnector;
100         bindHandlers();
101     }
102 
103     /**
104      * Performs some routine tasks needed by all item subApps before the view is displayed.
105      * The tasks are:
106      * <ul>
107      * <li>setting the current location
108      * <li>setting the presenter's view
109      * <li>calling {@link #onSubAppStart()} a hook-up method subclasses can override to perform additional work.
110      * </ul>
111      */
112     @Override
113     public ContentSubAppView start(final Location location) {
114         DetailLocation detailLocation = DetailLocation.wrap(location);
115         super.start(detailLocation);
116         // set caption
117         setCaption(detailLocation);
118         this.itemId = contentConnector.getItemIdByUrlFragment(detailLocation.getNodePath());
119 
120         View view;
121         if (detailLocation.hasVersion()) {
122             view = presenter.start(detailLocation.getNodePath(), detailLocation.getViewType(), contentConnector, detailLocation.getVersion());
123         } else {
124             view = presenter.start(detailLocation.getNodePath(), detailLocation.getViewType(), contentConnector);
125         }
126         getView().setContentView(view);
127         return getView();
128     }
129 
130     /**
131      * Wraps the current DefaultLocation in a ItemLocation. Providing getter and setters for used parameters.
132      */
133     @Override
134     public DetailLocation getCurrentLocation() {
135         return DetailLocation.wrap(super.getCurrentLocation());
136     }
137 
138     @Override
139     public boolean supportsLocation(Location location) {
140         DetailLocation itemLocation = DetailLocation.wrap(location);
141         String currentPath = getCurrentLocation().getNodePath();
142         return currentPath.equals(itemLocation.getNodePath());
143     }
144 
145     /**
146      * On location change, reload the view and tab caption.
147      */
148     @Override
149     public void locationChanged(Location location) {
150         DetailLocation detailLocation = DetailLocation.wrap(location);
151         if (!detailLocation.equals(getCurrentLocation())) {
152             setCaption(detailLocation);
153             View view = presenter.update(detailLocation);
154             getView().setContentView(view);
155         }
156     }
157 
158     @Override
159     public String getCaption() {
160         return caption;
161     }
162 
163     private void bindHandlers() {
164         adminCentralEventBus.addHandler(ContentChangedEvent.class, new ContentChangedEvent.Handler() {
165 
166             @Override
167             public void onContentChanged(ContentChangedEvent event) {
168                 // See if workspaces match
169                 if (contentConnector.canHandleItem(event.getItemId())) {
170                     // New item
171                     if (itemId == null) {
172                         // Check if parent is still existing, close supApp if it doesn't
173                         String currentNodePath = getCurrentLocation().getNodePath();
174 
175                         // resolve parent, removing trailing slash except for root
176                         int splitIndex = currentNodePath.lastIndexOf("/");
177                         if (splitIndex == 0) {
178                             splitIndex = 1;
179                         }
180                         String parentNodePath = currentNodePath.substring(0, splitIndex);
181                         Object parentItemId = contentConnector.getItemIdByUrlFragment(parentNodePath);
182                         if (!contentConnector.canHandleItem(parentItemId)) {
183                             getSubAppContext().close();
184                         }
185                         // Editing existing item
186                     } else {
187                         // Item (or parent) was deleted: close subApp
188                         if (!contentConnector.canHandleItem(itemId)) {
189                             getSubAppContext().close();
190                         }
191                         // Item still exists: update location if necessary
192                         else {
193                             String currentNodePath = getCurrentLocation().getNodePath();
194                             String itemPath = contentConnector.getItemUrlFragment(itemId);
195                             if (!currentNodePath.equals(itemPath)) {
196                                 DetailLocation location = DetailLocation.wrap(getSubAppContext().getLocation());
197                                 location.updateNodePath(itemPath);
198                                 // Update location
199                                 getSubAppContext().setLocation(location);
200                                 // Update Caption
201                                 setCaption(location);
202                             }
203                         }
204                     }
205                 }
206             }
207         });
208     }
209 
210     /**
211      * Set the Tab caption.
212      * If a version is part of the {@link DetailLocation}, add this version information to the Tab caption.
213      */
214     protected void setCaption(DetailLocation location) {
215         String caption = getBaseCaption(location);
216         // Set version information
217         if (StringUtils.isNotBlank(location.getVersion())) {
218             caption = i18n.translate("subapp.versioned_page", caption, location.getVersion() );
219         }
220         this.caption = caption;
221     }
222 
223     @Override
224     public String getIcon(Location location) {
225         if (itemId instanceof JcrNewNodeItemId || !contentConnector.canHandleItem(itemId)) {
226             return DetailView.ViewType.ADD.getIcon();
227         }
228 
229         DetailLocation detailLocation = DetailLocation.wrap(location);
230         return detailLocation.getViewType().getIcon();
231     }
232 
233     /**
234      * Create the base caption string.
235      * Default is the item path.
236      */
237     protected String getBaseCaption(DetailLocation location) {
238         return location.getNodePath();
239     }
240 
241 }