ref #9405 , ref #4944 refactor the cache protection indication handling in TaxEditor...
[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 element.addDependsOnCache(toggleableCache);
160 }
161 }
162 // updateCacheRelevance();
163 }
164
165 /**
166 * Updates the cache relevance state of all internal elements of this
167 * AbstractCdmDetailElement.
168 */
169 @Override
170 public void updateCacheRelevance(){
171 CacheRelevanceHelper.updateCacheRelevanceForSubelements(getElements());
172 }
173
174 /**
175 * Create all content elements
176 */
177 protected abstract void createControls(ICdmFormElement formElement,
178 T entity, int style);
179
180 @Override
181 public void propertyChange(PropertyChangeEvent event) {
182 if (event == null) {
183 return;
184 }
185
186 handleTitleCacheRelevantChange(event);
187
188 Object eventSource = event.getSource();
189
190 if (eventSource instanceof ICdmFormElement) {
191 ICdmFormElement eventElement = (ICdmFormElement) eventSource;
192 ICdmFormElement eventElementContainer = eventElement.getParentElement();
193 if (eventElementContainer == this) {
194 if (event instanceof CdmPropertyChangeEvent) {
195 if (((CdmPropertyChangeEvent) event).hasException()) {
196 handleException((CdmPropertyChangeEvent) event);
197 return;
198 }
199 }
200 // call specific handler implementation
201 handleEvent(eventSource);
202 // refire the event
203 firePropertyChangeEvent(this, event);
204 // update possible parents
205 updateParentSection();
206 }
207 }
208 }
209
210 protected void handleTitleCacheRelevantChange(PropertyChangeEvent event) {
211 boolean isRelevant = getEntity() instanceof TaxonName
212 || getEntity() instanceof TaxonBase;
213 isRelevant &= this instanceof AbstractIdentifiableEntityDetailElement;
214
215 if (isRelevant) {
216 ((AbstractIdentifiableEntityDetailElement<?>)this).updateToggleableCacheField();
217 }
218 }
219
220 private void updateParentSection() {
221 if (getParentElement() instanceof AbstractCdmDetailSection) {
222 ((AbstractCdmDetailSection<?>) getParentElement()).updateTitle();
223 }
224 //NOTE: This slows down the rendering of the details view
225 // StoreUtil.reflowParentScrolledForm(getLayoutComposite(), true);
226 }
227
228 /**
229 * Gets called when the source of the event is a child widget of this
230 * widget.
231 */
232 public abstract void handleEvent(Object eventSource);
233
234 public void handleException(CdmPropertyChangeEvent event) {
235 // override this in subclasses if you want to deal with the error
236 MessagingUtils.error(event.getSource().getClass(), event.getException());
237 }
238
239 @Override
240 public ConversationHolder getConversationHolder() {
241 if (getParentElement() instanceof IConversationEnabled) {
242 return ((IConversationEnabled) getParentElement())
243 .getConversationHolder();
244 }
245 throw new IllegalArgumentException(
246 "Parent element should be IConversationEnabled");
247 }
248
249 @Override
250 public void update(CdmDataChangeMap changeEvents) {
251 }
252
253 @Override
254 public void update(Observable o, Object arg){
255 if(o instanceof LoginManager){
256 updateControlStates();
257 }
258 }
259
260 protected void updateControlStates(){
261 Collection<Object> except = new ArrayList<Object>();
262 for(ICdmFormElement formElement:getElements()){
263 if(formElement instanceof IEnableableFormElement && !((IEnableableFormElement) formElement).isEnabled()){
264 except.add(formElement);
265 }
266 }
267 if (getEntity() != null && getEntity() instanceof CdmBase){
268 enabled = CdmStore.currentAuthentiationHasPermission(StoreUtil.getCdmEntity(getEntity()), requiredCrud);
269 }else{
270 enabled = true;
271 }
272 setEnabled(enabled, except);
273 }
274
275 public LabelElement getWarnForReferencedObjects() {
276 return warnForReferencedObjects;
277 }
278
279 public void setWarnForReferencedObjects(LabelElement warnForReferencedObjects) {
280 this.warnForReferencedObjects = warnForReferencedObjects;
281 }
282
283 public void setWarnForReferencingObjects(ICdmFormElement formElement, int defaultReferencingObjects){
284 if (getEntity() instanceof CdmBase){
285 CdmBase cdmBase = (CdmBase) getEntity();
286 if (cdmBase.getId() != 0){
287 long referencingObjectsCount = CdmStore.getCommonService().getReferencingObjectsCount(cdmBase);
288
289 if (referencingObjectsCount > defaultReferencingObjects){
290 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")));
291 getWarnForReferencedObjects().setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_RED));
292 getWarnForReferencedObjects().setLayout(LayoutConstants.FILL(2, 3));
293 getWarnForReferencedObjects().setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_RED));
294 formFactory.createLabel(formElement, "");
295 }
296 }
297 }
298 }
299
300 public void setWarnForReferencingObjects(ICdmFormElement formElement){
301 setWarnForReferencingObjects(formElement, 1);
302 }
303
304 public void setWarnForReferencingObjectsVisible(boolean isVisible){
305 if (getWarnForReferencedObjects() != null){
306 getWarnForReferencedObjects().setVisible(isVisible);
307 }
308 }
309 }