Merge branch 'release/5.19.0'
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / ui / section / AbstractCdmDetailElement.java
1 /**
2 * Copyright (C) 2007 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.taxeditor.ui.section;
10
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.EnumSet;
14 import java.util.Observable;
15 import java.util.Observer;
16
17 import org.eclipse.jface.util.PropertyChangeEvent;
18 import org.eclipse.swt.SWT;
19 import org.eclipse.swt.events.DisposeEvent;
20 import org.eclipse.swt.events.DisposeListener;
21 import org.eclipse.swt.widgets.Composite;
22 import org.eclipse.swt.widgets.Display;
23
24 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
25 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
26 import eu.etaxonomy.cdm.common.CdmUtils;
27 import eu.etaxonomy.cdm.model.common.CdmBase;
28 import eu.etaxonomy.cdm.model.name.TaxonName;
29 import eu.etaxonomy.cdm.model.permission.CRUD;
30 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
31 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
32 import eu.etaxonomy.taxeditor.model.MessagingUtils;
33 import eu.etaxonomy.taxeditor.store.CdmStore;
34 import eu.etaxonomy.taxeditor.store.LoginManager;
35 import eu.etaxonomy.taxeditor.store.StoreUtil;
36 import eu.etaxonomy.taxeditor.ui.element.AbstractRelevanceFormElement;
37 import eu.etaxonomy.taxeditor.ui.element.CacheRelevance;
38 import eu.etaxonomy.taxeditor.ui.element.CacheRelevanceHelper;
39 import eu.etaxonomy.taxeditor.ui.element.CdmFormFactory;
40 import eu.etaxonomy.taxeditor.ui.element.CdmPropertyChangeEvent;
41 import eu.etaxonomy.taxeditor.ui.element.ICacheRelevantFormElement;
42 import eu.etaxonomy.taxeditor.ui.element.ICdmFormElement;
43 import eu.etaxonomy.taxeditor.ui.element.IEnableableFormElement;
44 import eu.etaxonomy.taxeditor.ui.element.LabelElement;
45 import eu.etaxonomy.taxeditor.ui.element.LayoutConstants;
46 import eu.etaxonomy.taxeditor.ui.element.ToggleableTextElement;
47
48 /**
49 * @author n.hoffmann
50 * @created Feb 26, 2010
51 */
52 public abstract class AbstractCdmDetailElement<T>
53 extends AbstractRelevanceFormElement
54 implements ICdmDetailElement<T>, Observer{
55
56 private T entity;
57
58 protected boolean enabled = true;
59
60 private LabelElement warnForReferencedObjects;
61
62 protected EnumSet<CRUD> requiredCrud = null;
63
64 public AbstractCdmDetailElement(CdmFormFactory formFactory,
65 ICdmFormElement formElement) {
66 super(formFactory, formElement);
67 // register as property change listener
68 formFactory.addPropertyChangeListener(this);
69 CdmStore.getLoginManager().addObserver(this);
70
71 getLayoutComposite().getParent().addDisposeListener(new DisposeListener() {
72
73 @Override
74 public void widgetDisposed(DisposeEvent e) {
75 CdmStore.getLoginManager().deleteObserver(AbstractCdmDetailElement.this);
76 }
77 });
78 }
79
80 /**
81 * Sets the entity and updates controls
82 */
83 @Override
84 public void setEntity(T entity) {
85 this.entity = entity;
86 // the id is always 0 if the entity was not yet saved, so it is new in this case
87 if(getEntity() == null || (getEntity() instanceof CdmBase && StoreUtil.getCdmEntity(getEntity()).getId() == 0)) {
88 // new entity, not yet saved
89 requiredCrud = EnumSet.of(CRUD.CREATE);
90 } else {
91 requiredCrud = EnumSet.of(CRUD.UPDATE);
92 }
93 updateContent();
94 }
95
96 @Override
97 public T getEntity() {
98 return entity;
99 }
100
101 /**
102 * Updates all widgets to display the latest data
103 */
104 protected void updateContent() {
105 removeElements();
106 createControls(this, entity, SWT.NONE);
107 updateControlStates();
108 }
109
110 @Override
111 public void setSelected(boolean selected) {
112 Composite section = getLayoutComposite().getParent();
113 section.setBackground(selected ? SELECTED : getPersistentBackground());
114 }
115
116 /**
117 * Sets all field to the given enablement state except the objects in
118 * the collection except parameter.
119 *
120 * @see eu.etaxonomy.taxeditor.ui.element.IEnableableFormElement#setEnabled(boolean)
121 */
122 public void setEnabled(boolean enabled, Collection<Object> except) {
123 this.enabled = enabled;
124 for (ICdmFormElement element : getElements()) {
125 if (element instanceof IEnableableFormElement) {
126 IEnableableFormElement enableableElement = (IEnableableFormElement) element;
127 if (except != null && except.contains(enableableElement)) {
128 // enableableElement.setEnabled(enabled);
129 } else {
130 enableableElement.setEnabled(enabled);
131 }
132 }
133 }
134 }
135
136 @Override
137 public boolean isEnabled() {
138 return enabled;
139 }
140
141 @Override
142 public void setEnabled(boolean enabled) {
143 setEnabled(enabled, null);
144 }
145
146 @Override
147 public CacheRelevance cacheRelevance() {
148 return cacheRelevanceHelper.cacheRelevance();
149 }
150
151 @Override
152 public void addDependsOnCache(ToggleableTextElement toggleElement) {
153 cacheRelevanceHelper.addDependsOnCache(toggleElement);
154 }
155
156 protected void registerCacheRelevance(ICacheRelevantFormElement element, ToggleableTextElement... toggleableCaches) {
157 if (element != null && toggleableCaches != null) {
158 for (ToggleableTextElement toggleableCache : toggleableCaches){
159 if (toggleableCache != null){
160 element.addDependsOnCache(toggleableCache);
161 }
162 }
163 }
164 // updateCacheRelevance();
165 }
166
167 /**
168 * Updates the cache relevance state of all internal elements of this
169 * AbstractCdmDetailElement.
170 */
171 @Override
172 public void updateCacheRelevance(){
173 CacheRelevanceHelper.updateCacheRelevanceForSubelements(getElements());
174 }
175
176 /**
177 * Create all content elements
178 */
179 protected abstract void createControls(ICdmFormElement formElement,
180 T entity, int style);
181
182 @Override
183 public void propertyChange(PropertyChangeEvent event) {
184 if (event == null) {
185 return;
186 }
187
188 handleTitleCacheRelevantChange(event);
189
190 Object eventSource = event.getSource();
191
192 if (eventSource instanceof ICdmFormElement) {
193 ICdmFormElement eventElement = (ICdmFormElement) eventSource;
194 ICdmFormElement eventElementContainer = eventElement.getParentElement();
195 if (eventElementContainer == this) {
196 if (event instanceof CdmPropertyChangeEvent) {
197 if (((CdmPropertyChangeEvent) event).hasException()) {
198 handleException((CdmPropertyChangeEvent) event);
199 return;
200 }
201 }
202 // call specific handler implementation
203 handleEvent(eventSource);
204 // refire the event
205 firePropertyChangeEvent(this, event);
206 // update possible parents
207 updateParentSection();
208 }
209 }
210 }
211
212 protected void handleTitleCacheRelevantChange(PropertyChangeEvent event) {
213 boolean isRelevant = getEntity() instanceof TaxonName
214 || getEntity() instanceof TaxonBase;
215 isRelevant &= this instanceof AbstractIdentifiableEntityDetailElement;
216
217 if (isRelevant) {
218 ((AbstractIdentifiableEntityDetailElement<?>)this).updateToggleableCacheField();
219 }
220 }
221
222 private void updateParentSection() {
223 if (getParentElement() instanceof AbstractCdmDetailSection) {
224 ((AbstractCdmDetailSection<?>) getParentElement()).updateTitle();
225 }
226 //NOTE: This slows down the rendering of the details view
227 // StoreUtil.reflowParentScrolledForm(getLayoutComposite(), true);
228 }
229
230 /**
231 * Gets called when the source of the event is a child widget of this
232 * widget.
233 */
234 public abstract void handleEvent(Object eventSource);
235
236 public void handleException(CdmPropertyChangeEvent event) {
237 // override this in subclasses if you want to deal with the error
238 MessagingUtils.error(event.getSource().getClass(), event.getException());
239 }
240
241 @Override
242 public ConversationHolder getConversationHolder() {
243 if (getParentElement() instanceof IConversationEnabled) {
244 return ((IConversationEnabled) getParentElement())
245 .getConversationHolder();
246 }
247 throw new IllegalArgumentException(
248 "Parent element should be IConversationEnabled");
249 }
250
251 @Override
252 public void update(CdmDataChangeMap changeEvents) {
253 }
254
255 @Override
256 public void update(Observable o, Object arg){
257 if(o instanceof LoginManager){
258 updateControlStates();
259 }
260 }
261
262 protected void updateControlStates(){
263 Collection<Object> except = new ArrayList<Object>();
264 for(ICdmFormElement formElement:getElements()){
265 if(formElement instanceof IEnableableFormElement && !((IEnableableFormElement) formElement).isEnabled()){
266 except.add(formElement);
267 }
268 }
269 if (getEntity() != null && getEntity() instanceof CdmBase){
270 enabled = CdmStore.currentAuthentiationHasPermission(StoreUtil.getCdmEntity(getEntity()), requiredCrud);
271 }else{
272 enabled = true;
273 }
274 setEnabled(enabled, except);
275 }
276
277 public LabelElement getWarnForReferencedObjects() {
278 return warnForReferencedObjects;
279 }
280
281 public void setWarnForReferencedObjects(LabelElement warnForReferencedObjects) {
282 this.warnForReferencedObjects = warnForReferencedObjects;
283 }
284
285 public void setWarnForReferencingObjects(ICdmFormElement formElement, int defaultReferencingObjects){
286 if (getEntity() instanceof CdmBase){
287 CdmBase cdmBase = (CdmBase) getEntity();
288 if (cdmBase.getId() != 0){
289 long referencingObjectsCount = CdmStore.getCommonService().getReferencingObjectsCount(cdmBase);
290
291 if (referencingObjectsCount > defaultReferencingObjects){
292 setWarnForReferencedObjects(formFactory.createLabel(formElement, CdmUtils.Nz("The "+ cdmBase.getUserFriendlyTypeName()+" is referenced by " + referencingObjectsCount+ " objects, if you change it, it is changed for all these objects")));
293 getWarnForReferencedObjects().setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_RED));
294 getWarnForReferencedObjects().setLayout(LayoutConstants.FILL(2, 3));
295 getWarnForReferencedObjects().setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_RED));
296 formFactory.createLabel(formElement, "");
297 }
298 }
299 }
300 }
301
302 public void setWarnForReferencingObjects(ICdmFormElement formElement){
303 setWarnForReferencingObjects(formElement, 1);
304 }
305
306 public void setWarnForReferencingObjectsVisible(boolean isVisible){
307 if (getWarnForReferencedObjects() != null){
308 getWarnForReferencedObjects().setVisible(isVisible);
309 }
310 }
311 }