ref #6321 show progress bar in dialog
[taxeditor.git] / eu.etaxonomy.taxeditor.bulkeditor / src / main / java / eu / etaxonomy / taxeditor / bulkeditor / input / AbstractBulkEditorInput.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.bulkeditor.input;
10
11 import java.util.ArrayList;
12 import java.util.Comparator;
13 import java.util.HashMap;
14 import java.util.HashSet;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Map.Entry;
18 import java.util.Set;
19 import java.util.UUID;
20
21 import org.eclipse.core.runtime.ICoreRunnable;
22 import org.eclipse.core.runtime.jobs.Job;
23
24 import ca.odell.glazedlists.BasicEventList;
25 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
26 import eu.etaxonomy.cdm.api.service.config.DeleteConfiguratorBase;
27 import eu.etaxonomy.cdm.api.service.config.IIdentifiableEntityServiceConfigurator;
28 import eu.etaxonomy.cdm.api.service.exception.ReferencedObjectUndeletableException;
29 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
30 import eu.etaxonomy.cdm.model.common.CdmBase;
31 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
32 import eu.etaxonomy.cdm.model.common.MarkerType;
33 import eu.etaxonomy.cdm.strategy.merge.IMergable;
34 import eu.etaxonomy.cdm.strategy.merge.MergeException;
35 import eu.etaxonomy.taxeditor.annotatedlineeditor.IEntityCreator;
36 import eu.etaxonomy.taxeditor.annotatedlineeditor.IEntityPersistenceService;
37 import eu.etaxonomy.taxeditor.bulkeditor.BulkEditorQuery;
38 import eu.etaxonomy.taxeditor.bulkeditor.IBulkEditorSortProvider;
39 import eu.etaxonomy.taxeditor.bulkeditor.input.sortprovider.CdmBaseSortProvider;
40 import eu.etaxonomy.taxeditor.bulkeditor.input.sortprovider.TitleCacheComparator;
41 import eu.etaxonomy.taxeditor.bulkeditor.internal.TaxeditorBulkeditorPlugin;
42 import eu.etaxonomy.taxeditor.editor.CdmEntitySessionInput;
43 import eu.etaxonomy.taxeditor.l10n.Messages;
44 import eu.etaxonomy.taxeditor.model.MessagingUtils;
45 import eu.etaxonomy.taxeditor.store.CdmStore;
46
47 /**
48 * @author p.ciardelli
49 * @created 25.06.2009
50 * @version 1.0
51 * @param <T>
52 */
53 public abstract class AbstractBulkEditorInput<T extends CdmBase> extends CdmEntitySessionInput implements
54 IEntityPersistenceService<T> {
55
56 private UUID entityUuid;
57
58 private BasicEventList<T> model = new BasicEventList<>();
59
60 private Map<T, DeleteConfiguratorBase> toDelete = new HashMap<>();
61 private List<T> saveCandidates = new ArrayList<>();
62
63
64 private Set<T> markedMergeCandidates = new HashSet<>();
65 private T markedMergeTarget = null;
66
67 private HashMap<T, Set<T>> mergedEntities = new HashMap<>();
68
69 private IEntityCreator<T> entityCreator;
70 private final ConversationHolder conversation;
71
72 private Job searchJob;
73
74 public AbstractBulkEditorInput() {
75 super(true);
76 this.conversation = CdmStore.createConversation();
77 }
78
79 static public AbstractBulkEditorInput NewInstance(BulkEditorInputType inputType) {
80
81 return BulkEditorInputType.getInput(inputType);
82 }
83
84 public static AbstractBulkEditorInput NewInstance(IdentifiableEntity entity) {
85
86 BulkEditorInputType inputType = BulkEditorInputType.getByType(entity.getClass());
87
88 AbstractBulkEditorInput editorInput = NewInstance(inputType);
89
90 editorInput.setEntityUuid(entity.getUuid());
91
92 return editorInput;
93 }
94
95 public abstract String getName();
96
97 public String getEditorName(){
98 return getName();
99 }
100
101 protected int getPageSize(){
102 return 100;
103 }
104
105 protected abstract List<T> listEntities(IIdentifiableEntityServiceConfigurator configurator);
106
107 protected abstract long countEntities(IIdentifiableEntityServiceConfigurator configurator);
108
109 protected abstract T loadEntity(UUID entityUuid);
110
111 public void setMergeTarget(T t){
112 markedMergeTarget = t;
113 }
114
115 public Set<T> getMergeCandidates() {
116 return markedMergeCandidates;
117 }
118
119 public T getMergeTarget() {
120 return markedMergeTarget;
121 }
122
123 public void removeMergeTarget(){
124 markedMergeTarget = null;
125 }
126
127 public void addMergeCandidate(T t){
128 markedMergeCandidates.add(t);
129 }
130
131 public void removeMergeCandidate(T t){
132 markedMergeCandidates.remove(t);
133 }
134
135 public void addToDelete(T t, DeleteConfiguratorBase config) {
136 toDelete.put(t, config);
137 }
138 public void addSaveCandidate(T t){
139 saveCandidates.add(t);
140 }
141 private void setEntityUuid(UUID entityUuid){
142 this.entityUuid = entityUuid;
143 }
144
145 public UUID getEntityUuid() {
146 return entityUuid;
147 }
148
149 public void performSearch(final BulkEditorQuery bulkEditorQuery) {
150 //cancel previous search job
151 if(searchJob!=null && searchJob.getState()!=Job.NONE){
152 searchJob.cancel();
153 searchJob = null;
154 }
155 model.clear();
156
157 if(getEntityUuid() != null){
158
159 T entity = loadEntity(getEntityUuid());
160 model.add(entity);
161 }
162 else if(bulkEditorQuery != null){
163
164 IIdentifiableEntityServiceConfigurator configurator = bulkEditorQuery.getSearchConfigurator();
165 Comparator queryComparator = (bulkEditorQuery.getComparator() != null) ? bulkEditorQuery.getComparator() : new TitleCacheComparator();
166
167
168 int pageSize = configurator.getPageSize()!=null?configurator.getPageSize():getPageSize();
169 long count = countEntities(configurator);
170 int totalWork = count>Integer.MAX_VALUE?Integer.MAX_VALUE:(int)count;
171 String jobLabel = String.format(Messages.AbstractBulkEditorInput_LOADING, getName(), bulkEditorQuery.getSearchString());
172 searchJob = Job.create(jobLabel, (ICoreRunnable) monitor -> {
173 monitor.beginTask(jobLabel, totalWork);
174 int pageNumber = 0;
175 List<T> entities;
176 do {
177 if (monitor.isCanceled()) {
178 break;
179 }
180 configurator.setPageNumber(pageNumber);
181 entities = listEntities(configurator);
182 model.addAll(entities);
183 pageNumber++;
184 monitor.worked(pageSize);
185 long workedLong = pageSize*pageNumber;
186 int loadedCount = workedLong>Integer.MAX_VALUE?Integer.MAX_VALUE:(int)workedLong;
187 monitor.setTaskName(String.format(Messages.AbstractBulkEditorInput_LOADED, loadedCount, totalWork, getName()));
188 } while (!entities.isEmpty());
189 monitor.done();
190 });
191 searchJob.setUser(true);
192 searchJob.schedule();
193 }
194 }
195
196 public boolean isMergingEnabled() {
197 return false;
198 }
199
200 public boolean isConvertingEnabled() {
201 return false;
202 }
203
204 public boolean isMarkerTypeEditingEnabled(MarkerType markerType) {
205 return false;
206 }
207
208
209 /** {@inheritDoc} */
210 @Override
211 public boolean merge(T entity, T mergeTarget) {
212 if (entity instanceof IMergable) {
213 try {
214 CdmStore.getCommonService().merge(mergeTarget.getUuid(), entity.getUuid(), (Class<? extends CdmBase>)entity.getClass());
215 } catch (MergeException e) {
216 MessagingUtils.errorDialog(Messages.AbstractBulkEditorInput_MERGE_ERROR_TITLE,
217 this,
218 String.format(Messages.AbstractBulkEditorInput_MERGE_ERROR_MESSAGE, entity.getClass().getName()),
219 TaxeditorBulkeditorPlugin.PLUGIN_ID,
220 e,
221 true);
222 }
223 }
224 return true;
225 }
226
227 public void saveModel(){
228 saveModel(true);
229 }
230
231 public void saveModel(boolean resetMerge){
232 //delete entities
233 for(Entry<T, DeleteConfiguratorBase> entry:toDelete.entrySet()){
234 try {
235 delete(entry.getKey(), entry.getValue());
236 } catch (ReferencedObjectUndeletableException e) {
237 e.printStackTrace();
238 }
239 }
240 toDelete.clear();
241 if (!saveCandidates.isEmpty()){
242 CdmStore.getService(saveCandidates.get(0)).merge(saveCandidates, true);
243 }
244 if(resetMerge){
245 //merge entities
246 for(T mergeTarget:mergedEntities.keySet()){
247 for (T mergeCandidate: mergedEntities.get(mergeTarget)){
248 merge(mergeCandidate, mergeTarget);
249 }
250 }
251 mergedEntities.clear();
252
253 }
254 }
255
256
257 /** {@inheritDoc} */
258 @Override
259 public T create(T entity) {
260 return save(entity);
261 }
262
263 public IEntityCreator<T> getEntityCreator(){
264 if(entityCreator == null){
265 entityCreator = createEntityCreator();
266 }
267 return entityCreator;
268 }
269
270 protected abstract IEntityCreator<T> createEntityCreator();
271
272 /**
273 * The default implementation returns an empty list of sort providers.
274 * @return
275 */
276 public List<IBulkEditorSortProvider<T>> getSortProviders(){
277 List<IBulkEditorSortProvider<T>> sortProviders = new ArrayList<IBulkEditorSortProvider<T>>();
278
279 sortProviders.add(new CdmBaseSortProvider<T>());
280
281 return sortProviders;
282 }
283
284 /**
285 * Returns a textual representation given object. The default implementation
286 * in the abstract base class returns the simple name of the class, this may
287 * be overwritten to something more specific in subclasses.
288 *
289 * @param entity
290 * @return a textual representation given object.
291 */
292 public String getTypeText(Object entity){
293 return entity.getClass().getSimpleName();
294 }
295
296 public String getText(T entity) {
297 if(entity instanceof IdentifiableEntity){
298 IdentifiableEntity identifiableEntity = (IdentifiableEntity) HibernateProxyHelper.deproxy(entity);
299 String text = ""; //$NON-NLS-1$
300 if(markedMergeCandidates.contains(entity)){
301 text += Messages.AbstractBulkEditorInput_CANDIDATE;
302 }
303 else if(markedMergeTarget==entity){
304 text += Messages.AbstractBulkEditorInput_TARGET;
305 }
306 text += identifiableEntity.getTitleCache();
307 return text;
308 }
309
310 return "No text. Implement in subclass"; //$NON-NLS-1$
311 }
312
313 public BasicEventList<T> getModel() {
314 return model;
315 }
316
317 protected boolean replaceInModel(T entity) {
318 int index = model.indexOf(entity);
319 if(index >= 0) {
320 model.set(index, entity);
321 return true;
322 } else {
323 return false;
324 }
325 }
326
327 @Override
328 public List<T> getRootEntities() {
329 return getModel();
330 }
331
332
333 @Override
334 public Map<Object, List<String>> getPropertyPathsMap() {
335 // TODO Auto-generated method stub
336 return null;
337 }
338
339 public ConversationHolder getConversation() {
340 return conversation;
341 }
342
343 public List<T> getSaveCandidates() {
344 return saveCandidates;
345 }
346
347 /**
348 *
349 */
350 public void resetSaveCandidates() {
351 this.saveCandidates.clear();
352
353 }
354
355 public HashMap<T, Set<T>> getMergedEntities() {
356 return mergedEntities;
357 }
358
359 public void setMergedEntities(HashMap<T, Set<T>> mergedEntities) {
360 this.mergedEntities = mergedEntities;
361 }
362 }