Merge branch 'release/5.18.0'
[taxeditor.git] / eu.etaxonomy.taxeditor.cdmlib / src / main / java / eu / etaxonomy / taxeditor / session / CdmEntitySession.java
1 /**
2 * Copyright (C) 2014 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.session;
10
11 import java.util.ArrayList;
12 import java.util.Arrays;
13 import java.util.Collection;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.UUID;
17
18 import org.apache.log4j.Logger;
19
20 import eu.etaxonomy.cdm.api.service.IService;
21 import eu.etaxonomy.cdm.api.service.UpdateResult;
22 import eu.etaxonomy.cdm.cache.CdmTransientEntityCacher;
23 //import eu.etaxonomy.taxeditor.remoting.cache.CdmTransientEntityCacher;
24 import eu.etaxonomy.cdm.cache.EntityCacherDebugResult;
25 import eu.etaxonomy.cdm.model.common.CdmBase;
26 import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;
27 import eu.etaxonomy.cdm.persistence.dto.MergeResult;
28 import eu.etaxonomy.taxeditor.remoting.cache.ConversationalTransientEntityCacher;
29 import net.sf.ehcache.statistics.FlatStatistics;
30
31 /**
32 * NOTE : It would be nice to have this class performing merge / delete operations
33 * using services, but this is only possible if we can 'intelligently'
34 * get from a model class to the corresponding service class
35 *
36 * @author cmathew
37 * @date 20 Oct 2014
38 */
39 public class CdmEntitySession implements ICdmEntitySession {
40
41 private static final Logger logger = Logger.getLogger(CdmEntitySession.class);
42
43 private final CdmEntitySessionManager cdmEntitySessionManager;
44
45 private final ICdmEntitySessionEnabled sessionOwner;
46
47 private ConversationalTransientEntityCacher cdmTransientEntityCacher;
48
49 private List<ICdmEntitySessionEnabled> changeObservers;
50
51 public CdmEntitySession(ICdmEntitySessionEnabled sessionOwner, CdmEntitySessionManager cdmEntitySessionManager) {
52 this.sessionOwner = sessionOwner;
53 this.cdmEntitySessionManager = cdmEntitySessionManager;
54 init(sessionOwner, cdmEntitySessionManager);
55 }
56
57 private void init(ICdmEntitySessionEnabled sessionOwner, CdmEntitySessionManager cdmEntitySessionManager) {
58 this.cdmTransientEntityCacher = new ConversationalTransientEntityCacher(sessionOwner);
59 this.changeObservers = new ArrayList<>();
60 cdmEntitySessionManager.addToOwnerSessionMap(sessionOwner, this);
61 }
62
63 @Override
64 public <O extends Object> O load(O obj, boolean update) {
65 return cdmTransientEntityCacher.load(obj, update);
66 }
67
68 @Override
69 public <T extends CdmBase> T load(T cdmBase, boolean update) {
70 return cdmTransientEntityCacher.load(cdmBase, update);
71 }
72
73 @Override
74 public UpdateResult load(UpdateResult updateResult, boolean update) {
75 return cdmTransientEntityCacher.load(updateResult, update);
76 }
77
78 @Override
79 public <T extends CdmBase> MergeResult<T> load(MergeResult<T> mergeResult, boolean update) {
80 return cdmTransientEntityCacher.load(mergeResult, update);
81 }
82
83 @Override
84 public <T extends CdmBase> void update() {
85 Collection<T> rootEntities = getRootEntities();
86 if(rootEntities != null) {
87 for(T rootEntity : rootEntities) {
88 load(rootEntity, true);
89 }
90 }
91 }
92
93 // @Override
94 // public <T extends ICdmBase> void update(T cdmBase, Set<CdmBase> affectedObjects) {
95 // addEvent(cdmBase, affectedObjects, EventType.UPDATE);
96 // }
97 //
98 // @Override
99 // public <T extends ICdmBase> void update(T cdmBase, CdmBase affectedObject) {
100 // Set<CdmBase> set = new HashSet<CdmBase>();
101 // set.add(affectedObject);
102 // addEvent(cdmBase, set, EventType.UPDATE);
103 // }
104 //
105 //
106 // @Override
107 // public <T extends ICdmBase> void delete(T cdmBase, Set<CdmBase> affectedObjects) {
108 // addEvent(cdmBase, affectedObjects, EventType.DELETE);
109 // }
110 //
111 // @Override
112 // public <T extends ICdmBase> void delete(Set<T> cdmBases, Set<CdmBase> affectedObjects) {
113 // addEvent(cdmBases, affectedObjects, EventType.DELETE);
114 // }
115
116
117 @Override
118 public <T extends CdmBase> EntityCacherDebugResult debug(T cdmBase) {
119 return debug(Arrays.asList(cdmBase), true);
120 }
121
122 @Override
123 public <T extends CdmBase> EntityCacherDebugResult debug(Collection<T> rootEntities, boolean includeIgnored) {
124 EntityCacherDebugResult entityCacherDebugResult =
125 new EntityCacherDebugResult(cdmTransientEntityCacher, rootEntities, includeIgnored);
126 return entityCacherDebugResult;
127 }
128
129 @Override
130 public <T extends CdmBase> EntityCacherDebugResult debug(boolean includeIgnored) {
131 return debug(getRootEntities(), includeIgnored);
132 }
133
134 @Override
135 public <T extends CdmBase> Collection<T> load(Collection<T> cdmBaseList, boolean update) {
136 return cdmTransientEntityCacher.load(cdmBaseList, update);
137 }
138
139 @Override
140 public void setEntitiesAsLatest() {
141 //FIXME:Remoting need to think more about whether we really need this
142 // List<CdmBase> entities = cdmTransientEntityCacher.getAllEntities();
143 // for(CdmBase entity : entities) {
144 // cdmEntitySessionManager.setEntityAsLatest(entity);
145 // }
146 }
147
148 @Override
149 public void bind() {
150 logger.info("Binding session with owner " + sessionOwner.toString());
151 if(!cdmEntitySessionManager.contains(sessionOwner)) {
152 init(sessionOwner, cdmEntitySessionManager);
153 }
154 cdmEntitySessionManager.bind(sessionOwner);
155 }
156
157 @Override
158 public void dispose() {
159
160 cdmTransientEntityCacher.dispose();
161 changeObservers.clear();
162 cdmEntitySessionManager.remove(sessionOwner);
163 }
164
165 // @Override
166 // public void addEvent(ICdmBase cdmBase, Set<CdmBase> affectedObjects, EventType eventType) {
167 // affectedObjects = (Set<CdmBase>) load(affectedObjects, true);
168 // CdmDataChangeEvent cdce = CdmDataChangeEvent.NewInstance((CdmBase)cdmBase, affectedObjects, eventType);
169 // CdmPostDataChangeObservableListener.getDefault().notifyObservers(cdce);
170 // }
171
172 /**
173 * Returns a persisted entity specified by the <code>uuid</code>
174 * or null if the entity does not exist,
175 * loads it to the entityCacher
176 *
177 * @param service
178 * @param uuid
179 *
180 * @return
181 */
182 @Override
183 public <T extends CdmBase> T remoteLoad(IService<T> service, UUID uuid) {
184 T cdmBase = service.load(uuid);
185 return load(cdmBase, false);
186 }
187
188 /**
189 * Returns the cdm entity specified by the <code>uuid</code>,
190 * recursively initializes all bean properties given in the
191 * <code>propertyPaths</code> parameter,
192 * the loaded entity is also loaded to the entityCache
193 * <p>
194 * For detailed description and examples <b>please refer to:</b>
195 * {@link IBeanInitializer#initialize(Object, List)}
196 *
197 * @param service
198 * @param uuid
199 * @param propertyPath
200 *
201 * @return
202 */
203 @Override
204 public <T extends CdmBase> T remoteLoad(IService<T> service, UUID uuid, List<String> propertyPaths) {
205 T cdmBase = service.load(uuid, propertyPaths);
206 return load(cdmBase, false);
207 }
208
209 @Override
210 public <T extends CdmBase> UUID remoteSave(IService<T> service, T cdmBase) {
211 UUID uuid = service.save(cdmBase).getUuid();
212 load(cdmBase,false);
213 return uuid;
214 }
215
216 @Override
217 public <T extends CdmBase> T remoteUpdate(IService<T> service, T cdmBase) {
218 T mergedCdmBase = service.merge(cdmBase, true).getMergedEntity();
219 return mergedCdmBase;
220 }
221
222 @Override
223 public boolean isActive() {
224 return cdmEntitySessionManager.getActiveSession() == this;
225 }
226
227 @Override
228 public ICdmEntitySessionEnabled getOwner() {
229 return sessionOwner;
230 }
231
232 @Override
233 public FlatStatistics getCacheStatistics() {
234 return cdmTransientEntityCacher.getCacheStatistics();
235 }
236
237 @Override
238 public <T extends CdmBase> Collection<T> getRootEntities() {
239 return sessionOwner.getRootEntities();
240 }
241
242 public CdmTransientEntityCacher getCacher() {
243 return cdmTransientEntityCacher;
244 }
245
246 @Override
247 public List<String> getPropertyPaths(Object obj) {
248 Map<Object, List<String>> propertyPathsMap = sessionOwner.getPropertyPathsMap();
249 if(propertyPathsMap == null || propertyPathsMap.isEmpty()) {
250 return null;
251 }
252 return propertyPathsMap.get(obj);
253 }
254
255 //this method is called by DefaultNewEntityListener whenever
256 //a new entity is created (constructor call) while the current
257 //session is active
258 @Override
259 public void addNewCdmEntity(CdmBase newEntity) {
260 cdmTransientEntityCacher.load(newEntity);
261 }
262 }