adapt master to develop
[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.Collection;
12 import java.util.EnumSet;
13 import java.util.Observable;
14 import java.util.Observer;
15
16 import org.eclipse.jface.util.PropertyChangeEvent;
17 import org.eclipse.swt.SWT;
18 import org.eclipse.swt.widgets.Composite;
19 import org.eclipse.swt.widgets.Display;
20
21 import eu.etaxonomy.cdm.common.CdmUtils;
22 import eu.etaxonomy.cdm.model.common.CdmBase;
23 import eu.etaxonomy.cdm.model.name.TaxonName;
24 import eu.etaxonomy.cdm.model.permission.CRUD;
25 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
26 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
27 import eu.etaxonomy.taxeditor.model.MessagingUtils;
28 import eu.etaxonomy.taxeditor.store.CdmStore;
29 import eu.etaxonomy.taxeditor.store.LoginManager;
30 import eu.etaxonomy.taxeditor.store.StoreUtil;
31 import eu.etaxonomy.taxeditor.ui.element.AbstractRelevanceFormElement;
32 import eu.etaxonomy.taxeditor.ui.element.CacheRelevance;
33 import eu.etaxonomy.taxeditor.ui.element.CacheRelevanceHelper;
34 import eu.etaxonomy.taxeditor.ui.element.CdmFormFactory;
35 import eu.etaxonomy.taxeditor.ui.element.CdmPropertyChangeEvent;
36 import eu.etaxonomy.taxeditor.ui.element.ICacheRelevantFormElement;
37 import eu.etaxonomy.taxeditor.ui.element.ICdmFormElement;
38 import eu.etaxonomy.taxeditor.ui.element.IEnableableFormElement;
39 import eu.etaxonomy.taxeditor.ui.element.LabelElement;
40 import eu.etaxonomy.taxeditor.ui.element.LayoutConstants;
41 import eu.etaxonomy.taxeditor.ui.element.ToggleableTextElement;
42
43 /**
44 * @author n.hoffmann
45 * @created Feb 26, 2010
46 */
47 public abstract class AbstractCdmDetailElement<T>
48 extends AbstractRelevanceFormElement
49 implements ICdmDetailElement<T>, Observer{
50
51 private T entity;
52
53 protected boolean enabled = true;
54
55 private LabelElement warnForReferencedObjects;
56
57 protected EnumSet<CRUD> requiredCrud = null;
58
59 public AbstractCdmDetailElement(CdmFormFactory formFactory,
60 ICdmFormElement formElement) {
61 super(formFactory, formElement);
62 // register as property change listener
63 formFactory.addPropertyChangeListener(this);
64 CdmStore.getLoginManager().addObserver(this);
65
66 getLayoutComposite().getParent().addDisposeListener(
67 e -> CdmStore.getLoginManager().deleteObserver(AbstractCdmDetailElement.this));
68 }
69
70 /**
71 * Sets the entity and updates controls
72 */
73 @Override
74 public void setEntity(T entity) {
75 this.entity = entity;
76 // the id is always 0 if the entity was not yet saved, so it is new in this case
77 if(getEntity() == null || (getEntity() instanceof CdmBase && StoreUtil.getCdmEntity(getEntity()).getId() == 0)) {
78 // new entity, not yet saved
79 requiredCrud = EnumSet.of(CRUD.CREATE);
80 } else {
81 requiredCrud = EnumSet.of(CRUD.UPDATE);
82 }
83 updateContent();
84 }
85
86 public void setEntityWithoutUpdate(T entity){
87 this.entity = entity;
88 fillFields();
89 }
90
91 public abstract void fillFields();
92
93 @Override
94 public T getEntity() {
95 return entity;
96 }
97
98 /**
99 * Updates all widgets to display the latest data
100 */
101 protected void updateContent() {
102 removeElements();
103 createControls(this, entity, SWT.NONE);
104 updateControlStates();
105 }
106
107 @Override
108 public void setSelected(boolean selected) {
109 Composite section = getLayoutComposite().getParent();
110 section.setBackground(selected ? SELECTED : getPersistentBackground());
111 }
112
113 /**
114 * Sets all field to the given enablement state except the objects in
115 * the collection except parameter.
116 *
117 * @see eu.etaxonomy.taxeditor.ui.element.IEnableableFormElement#setEnabled(boolean)
118 */
119 public void setEnabled(boolean enabled, Collection<Object> except) {
120 boolean enabled_old = this.enabled;
121 this.enabled = enabled;
122 if (this.enabled != enabled_old){
123 for (ICdmFormElement element : getElements()) {
124 if (element instanceof IEnableableFormElement) {
125 IEnableableFormElement enableableElement = (IEnableableFormElement) element;
126 if (except != null && except.contains(enableableElement)) {
127 // enableableElement.setEnabled(enabled);
128 } else {
129 enableableElement.setEnabled(enabled);
130 }
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
242
243 @Override
244 public void update(Observable o, Object arg){
245 if(o instanceof LoginManager){
246 updateControlStates();
247 }
248 }
249
250 protected void updateControlStates(){
251 if (getEntity() != null && getEntity() instanceof CdmBase){
252 enabled = enabled && CdmStore.currentAuthentiationHasPermission(StoreUtil.getCdmEntity(getEntity()), requiredCrud);
253 }else{
254 enabled = true;
255 }
256 setEnabled(enabled);
257 }
258
259 public LabelElement getWarnForReferencedObjects() {
260 return warnForReferencedObjects;
261 }
262
263 public void setWarnForReferencedObjects(LabelElement warnForReferencedObjects) {
264 this.warnForReferencedObjects = warnForReferencedObjects;
265 }
266
267 public void setWarnForReferencingObjects(ICdmFormElement formElement, int defaultReferencingObjects){
268 if (getEntity() instanceof CdmBase){
269 CdmBase cdmBase = (CdmBase) getEntity();
270 if (cdmBase.getId() != 0){
271 long referencingObjectsCount = CdmStore.getCommonService().getReferencingObjectsCount(cdmBase);
272
273 if (referencingObjectsCount > defaultReferencingObjects){
274 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")));
275 getWarnForReferencedObjects().setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_RED));
276 getWarnForReferencedObjects().setLayout(LayoutConstants.FILL(2, 3));
277 getWarnForReferencedObjects().setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_RED));
278 formFactory.createLabel(formElement, "");
279 }
280 }
281 }
282 }
283
284 public void setWarnForReferencingObjects(ICdmFormElement formElement){
285 setWarnForReferencingObjects(formElement, 1);
286 }
287
288 public void setWarnForReferencingObjectsVisible(boolean isVisible){
289 if (getWarnForReferencedObjects() != null){
290 getWarnForReferencedObjects().setVisible(isVisible);
291 }
292 }
293 }