e0808495073073b1664da7c8878fbe958953e0eb
[cdm-vaadin.git] / src / main / java / eu / etaxonomy / cdm / vaadin / ui / AbstractUI.java
1 /**
2 * Copyright (C) 2021 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9 package eu.etaxonomy.cdm.vaadin.ui;
10
11 import org.apache.logging.log4j.LogManager;
12 import org.apache.logging.log4j.Logger;
13 import org.springframework.beans.factory.annotation.Autowired;
14 import org.vaadin.spring.events.EventBus.UIEventBus;
15
16 import com.flowingcode.vaadin.addons.errorwindow.WindowErrorHandler;
17 import com.vaadin.navigator.View;
18 import com.vaadin.navigator.ViewDisplay;
19 import com.vaadin.server.ExternalResource;
20 import com.vaadin.server.Page;
21 import com.vaadin.server.Resource;
22 import com.vaadin.server.Responsive;
23 import com.vaadin.server.VaadinRequest;
24 import com.vaadin.server.VaadinSession;
25 import com.vaadin.spring.navigator.SpringViewProvider;
26 import com.vaadin.ui.Component;
27 import com.vaadin.ui.UI;
28 import com.vaadin.ui.themes.ValoTheme;
29
30 import eu.etaxonomy.cdm.addon.config.UIDisabledException;
31 import eu.etaxonomy.cdm.persistence.permission.PermissionDeniedException;
32 import eu.etaxonomy.cdm.vaadin.event.error.DelegatingErrorHandler;
33 import eu.etaxonomy.cdm.vaadin.event.error.ErrorTypeErrorHandlerWrapper;
34 import eu.etaxonomy.cdm.vaadin.event.error.PermissionDeniedErrorHandler;
35 import eu.etaxonomy.cdm.vaadin.event.error.UIDisabledErrorHandler;
36 import eu.etaxonomy.cdm.vaadin.permission.ReleasableResourcesView;
37 import eu.etaxonomy.cdm.vaadin.view.RedirectToLoginView;
38 import eu.etaxonomy.vaadin.ui.UIInitializedEvent;
39 import eu.etaxonomy.vaadin.ui.navigation.NavigationManagerBean;
40
41 /**
42 * @author a.kohlbecker
43 * @since Nov 11, 2021
44 */
45 public abstract class AbstractUI extends UI {
46
47 private static final long serialVersionUID = 7430086500775997281L;
48
49 private static final Logger logger = LogManager.getLogger();
50
51 abstract protected ViewDisplay getViewDisplay();
52
53 @Autowired
54 protected SpringViewProvider viewProvider;
55
56 @Autowired
57 final private void setNavigationManagerBean(NavigationManagerBean navigatorBean) {
58 // logger.debug("setNavigationManagerBean()" + navigatorBean.toString());
59 setNavigator(navigatorBean);
60 }
61
62 final private NavigationManagerBean getNavigationManagerBean() {
63 if(getNavigator() != null) {
64 return (NavigationManagerBean) getNavigator();
65 }
66 return null;
67 }
68
69 @Autowired
70 protected UIEventBus uiEventBus;
71
72 // private boolean enabled;
73
74 public AbstractUI() {
75 super();
76 }
77
78 public AbstractUI(Component content) {
79 super(content);
80 }
81
82 @Override
83 protected void init(VaadinRequest request) {
84
85 logger.debug(this.getClass().getSimpleName() + ".init()");
86 registerErrorHandlers();
87
88 configureAccessDeniedView();
89
90 assert getInitialViewName() != null;
91 assert getViewDisplay() != null;
92
93 logger.debug(this.getClass().getSimpleName() + ".init() ViewDisplay: " + getViewDisplay().getClass().getSimpleName() + ", initialViewName: " + getInitialViewName());
94
95 if(!isEnabled()) {
96 throw new UIDisabledException(getClass().getSimpleName());
97 }
98
99 initAdditionalContent();
100
101 getNavigationManagerBean().setViewDisplay(getViewDisplay());
102 getNavigationManagerBean().setDefaultViewName(getInitialViewName());
103
104 Responsive.makeResponsive(this);
105
106 addDetachListener(e -> {
107 if(getNavigator() != null) {
108 // no point using viewProvider.getView() without the navigator
109 for(String viewName : viewProvider.getViewNamesForCurrentUI()){
110 View view = viewProvider.getView(viewName);
111 if(view != null && view instanceof ReleasableResourcesView) {
112 ((ReleasableResourcesView)view).releaseResourcesOnAccessDenied();
113 }
114 }
115 }
116 });
117
118 if(getBrandName() != null) {
119 //TODO create annotation:
120 // @Styles(files={""}, branding="brand")
121 //
122 // the branding can either be specified or can be read from the properties file in .cdmLibrary/remote-webapp/{instance-name}-app.properties
123 // See CdmUtils for appropriate methods to access this folder
124 // the 'vaadin://' protocol refers to the VAADIN folder
125 Resource registryCssFile = new ExternalResource("vaadin://branding/" + getBrandName() + "/css/branding.css");
126 Page.getCurrent().getStyles().add(registryCssFile);
127 }
128
129 uiEventBus.publish(this, new UIInitializedEvent());
130 }
131
132 // /**
133 // * @return
134 // */
135 // @Override
136 // protected abstract String getUIName();
137
138 /**
139 * @return The name of the initial view to show
140 */
141 abstract protected String getInitialViewName();
142
143 /**
144 * Branding can either be specified or can be read from the properties file
145 * in <code>.cdmLibrary/remote-webapp/{instance-name}-app.properties</code>
146 * See CdmUtils for appropriate methods to access this folder the
147 * <code>'vaadin://'</code> protocol refers to the VAADIN folder.
148 * <p>
149 * Can be overridden by implementing classes to set a brand.
150 *
151 * @return <code>NULL</code> for no branding or
152 */
153 protected String getBrandName() {
154 return null;
155 }
156
157 /**
158 * Implementing classes may add additional content to the UI. This
159 * will for example be interesting when using the {@link ValoTheme.UI_WITH_MENU}
160 * style.
161 */
162 abstract protected void initAdditionalContent();
163
164 protected void registerErrorHandlers() {
165 DelegatingErrorHandler delegatingErrorHander = new DelegatingErrorHandler();
166 WindowErrorHandler errorHandler = new WindowErrorHandler(
167 this,
168 RegistrationUIDefaults.ERROR_CONTACT_MESSAGE_LINE + "</br></br>"
169 + "<i>To help analyzing the problem please describe your actions that lead to this error and provide the error details from below in your email. "
170 + "You also might want to add a sreenshot of the browser page in error.</i>");
171 delegatingErrorHander.registerHandler(
172 new ErrorTypeErrorHandlerWrapper<PermissionDeniedException>(PermissionDeniedException.class, new PermissionDeniedErrorHandler(this))
173 );
174 delegatingErrorHander.registerHandler(
175 new ErrorTypeErrorHandlerWrapper<UIDisabledException>(UIDisabledException.class, new UIDisabledErrorHandler(this))
176 );
177 delegatingErrorHander.registerHandler(
178 new ErrorTypeErrorHandlerWrapper<Exception>(Exception.class, errorHandler)
179 );
180 setErrorHandler(delegatingErrorHander);
181 VaadinSession.getCurrent().setErrorHandler(delegatingErrorHander);
182 }
183
184 protected void configureAccessDeniedView() {
185 viewProvider.setAccessDeniedViewClass(RedirectToLoginView.class);
186 }
187
188 private String pageFragmentAsState() {
189 Page page = Page.getCurrent();
190 String fragment = page.getUriFragment();
191 String state = null;
192 if(fragment != null && fragment.startsWith("!")){
193 state = fragment.substring(1, fragment.length());
194 }
195 return state;
196 }
197
198 // @Override
199 // public void setEnabled(boolean state) {
200 // this.enabled = state;
201 // }
202 //
203 // @Override
204 // public boolean isEnabled() {
205 // return enabled;
206 // }
207
208
209 }