Project

General

Profile

Download (11.1 KB) Statistics
| Branch: | Tag: | Revision:
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
import org.eclipse.jface.viewers.IStructuredSelection;
24

    
25
import ca.odell.glazedlists.BasicEventList;
26
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
27
import eu.etaxonomy.cdm.api.service.config.DeleteConfiguratorBase;
28
import eu.etaxonomy.cdm.api.service.config.IIdentifiableEntityServiceConfigurator;
29
import eu.etaxonomy.cdm.api.service.exception.ReferencedObjectUndeletableException;
30
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
31
import eu.etaxonomy.cdm.model.common.CdmBase;
32
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
33
import eu.etaxonomy.cdm.model.common.MarkerType;
34
import eu.etaxonomy.cdm.strategy.merge.IMergable;
35
import eu.etaxonomy.cdm.strategy.merge.MergeException;
36
import eu.etaxonomy.taxeditor.annotatedlineeditor.IEntityCreator;
37
import eu.etaxonomy.taxeditor.annotatedlineeditor.IEntityPersistenceService;
38
import eu.etaxonomy.taxeditor.bulkeditor.BulkEditorQuery;
39
import eu.etaxonomy.taxeditor.bulkeditor.IBulkEditorSortProvider;
40
import eu.etaxonomy.taxeditor.bulkeditor.input.sortprovider.CdmBaseSortProvider;
41
import eu.etaxonomy.taxeditor.bulkeditor.input.sortprovider.TitleCacheComparator;
42
import eu.etaxonomy.taxeditor.bulkeditor.internal.TaxeditorBulkeditorPlugin;
43
import eu.etaxonomy.taxeditor.editor.CdmEntitySessionInput;
44
import eu.etaxonomy.taxeditor.event.EventUtility;
45
import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
46
import eu.etaxonomy.taxeditor.l10n.Messages;
47
import eu.etaxonomy.taxeditor.model.MessagingUtils;
48
import eu.etaxonomy.taxeditor.store.CdmStore;
49

    
50
/**
51
 * @author p.ciardelli
52
 * @created 25.06.2009
53
 * @version 1.0
54
 * @param <T>
55
 */
56
public abstract class AbstractBulkEditorInput<T extends CdmBase> extends CdmEntitySessionInput implements
57
    IEntityPersistenceService<T> {
58

    
59
	private UUID entityUuid;
60

    
61
	private BasicEventList<T> model = new BasicEventList<>();
62

    
63
	private Map<T, DeleteConfiguratorBase> toDelete = new HashMap<>();
64
	private Set<T> saveCandidates = new HashSet<>();
65

    
66

    
67
	private Set<T> markedMergeCandidates = new HashSet<>();
68
	private T markedMergeTarget = null;
69

    
70
	private HashMap<T, Set<T>> mergedEntities = new HashMap<>();
71

    
72
	private IEntityCreator<T> entityCreator;
73
	private final ConversationHolder conversation;
74

    
75
    private Job searchJob;
76

    
77
	public AbstractBulkEditorInput() {
78
	    super(true);
79
	    this.conversation = CdmStore.createConversation();
80
	}
81

    
82
	static public AbstractBulkEditorInput NewInstance(BulkEditorInputType inputType) {
83

    
84
		return BulkEditorInputType.getInput(inputType);
85
	}
86

    
87
	public static AbstractBulkEditorInput NewInstance(IdentifiableEntity entity) {
88

    
89
		BulkEditorInputType inputType = BulkEditorInputType.getByType(entity.getClass());
90

    
91
		AbstractBulkEditorInput editorInput = NewInstance(inputType);
92

    
93
		editorInput.setEntityUuid(entity.getUuid());
94

    
95
		return editorInput;
96
	}
97

    
98
    public abstract String getName();
99

    
100
    public String getEditorName(){
101
        return getName();
102
    }
103

    
104
    protected int getPageSize(){
105
        return 100;
106
    }
107

    
108
	protected abstract List<T> listEntities(IIdentifiableEntityServiceConfigurator configurator);
109

    
110
	protected abstract long countEntities(IIdentifiableEntityServiceConfigurator configurator);
111

    
112
	protected abstract T loadEntity(UUID entityUuid);
113

    
114
	public Comparator<T> getTitleComparator(){
115
	    return new TitleCacheComparator();
116
	}
117

    
118
	public void setMergeTarget(T t){
119
	    markedMergeTarget = t;
120
	}
121

    
122
    public Set<T> getMergeCandidates() {
123
        return markedMergeCandidates;
124
    }
125

    
126
    public T getMergeTarget() {
127
        return markedMergeTarget;
128
    }
129

    
130
	public void removeMergeTarget(){
131
	    markedMergeTarget = null;
132
	}
133

    
134
	public void addMergeCandidate(T t){
135
	    markedMergeCandidates.add(t);
136
	}
137

    
138
	public void removeMergeCandidate(T t){
139
		markedMergeCandidates.remove(t);
140
	}
141

    
142
    public void addToDelete(T t, DeleteConfiguratorBase config) {
143
        toDelete.put(t, config);
144
    }
145
    public void addSaveCandidate(T t){
146
        saveCandidates.add(t);
147
    }
148
	private void setEntityUuid(UUID entityUuid){
149
		this.entityUuid = entityUuid;
150
	}
151

    
152
	public UUID getEntityUuid() {
153
		return entityUuid;
154
	}
155

    
156
	public void performSearch(final BulkEditorQuery bulkEditorQuery, IStructuredSelection selection) {
157
	    //cancel previous search job
158
	    if(searchJob!=null && searchJob.getState()!=Job.NONE){
159
	        searchJob.cancel();
160
	        searchJob = null;
161
	    }
162
	    model.clear();
163

    
164
		if(getEntityUuid() != null){
165

    
166
			T entity = loadEntity(getEntityUuid());
167
			model.add(entity);
168
		}
169
		else if(bulkEditorQuery != null){
170
            IIdentifiableEntityServiceConfigurator configurator = bulkEditorQuery.getSearchConfigurator();
171

    
172
            // check for UUID search
173
            String titleSearchString = configurator.getTitleSearchString();
174
            try {
175
                UUID uuid = UUID.fromString(titleSearchString);
176
                T entity = loadEntity(uuid);
177
                //UUID search found -> add entity to list and return
178
                model.add(entity);
179
                return;
180
            } catch (IllegalArgumentException e) {
181
                // search string was no UUID
182
            }
183
            //-> continue with standard search
184

    
185
            int pageSize = configurator.getPageSize()!=null?configurator.getPageSize():getPageSize();
186
            configurator.setPageSize(pageSize);
187
			long count = countEntities(configurator);
188
			int totalWork = count>Integer.MAX_VALUE?Integer.MAX_VALUE:(int)count;
189
			String jobLabel = String.format(Messages.AbstractBulkEditorInput_LOADING, getName(), bulkEditorQuery.getSearchString());
190
	        searchJob = Job.create(jobLabel, (ICoreRunnable) monitor -> {
191
	            monitor.beginTask(jobLabel, totalWork);
192
	            int pageNumber = 0;
193
	            List<T> entities;
194
                do {
195
                    if (monitor.isCanceled()) {
196
                        break;
197
                    }
198
                    configurator.setPageNumber(pageNumber);
199
                    entities = listEntities(configurator);
200
                    model.addAll(entities);
201
                    //select if entity is loaded
202
                    if(selection!=null && model.containsAll(selection.toList())){
203
                        EventUtility.postAsyncEvent(WorkbenchEventConstants.BULK_EDITOR_SEARCH_FINISHED, selection);
204
                    }
205
                    pageNumber++;
206
                    monitor.worked(pageSize);
207
                    long workedLong = pageSize*pageNumber;
208
                    int loadedCount =  workedLong>Integer.MAX_VALUE?Integer.MAX_VALUE:(int)workedLong;
209
                    monitor.setTaskName(String.format(Messages.AbstractBulkEditorInput_LOADED, loadedCount, totalWork, getName()));
210
                } while (!entities.isEmpty());
211
	            monitor.done();
212
	            EventUtility.postAsyncEvent(WorkbenchEventConstants.BULK_EDITOR_SEARCH_FINISHED, selection);
213
	        });
214
	        searchJob.schedule();
215
		}
216
	}
217

    
218
	public boolean isMergingEnabled() {
219
		return false;
220
	}
221

    
222
	public boolean isConvertingEnabled() {
223
		return false;
224
	}
225

    
226
	public boolean isMarkerTypeEditingEnabled(MarkerType markerType) {
227
		return false;
228
	}
229

    
230

    
231
	/** {@inheritDoc} */
232
	@Override
233
    public boolean merge(T entity, T mergeTarget) {
234
		if (entity instanceof IMergable) {
235
			try {
236
				CdmStore.getCommonService().merge(mergeTarget.getUuid(), entity.getUuid(), (Class<? extends CdmBase>)entity.getClass());
237
			} catch (MergeException e) {
238
				MessagingUtils.errorDialog(Messages.AbstractBulkEditorInput_MERGE_ERROR_TITLE,
239
						this,
240
						String.format(Messages.AbstractBulkEditorInput_MERGE_ERROR_MESSAGE, entity.getClass().getName()),
241
						TaxeditorBulkeditorPlugin.PLUGIN_ID,
242
						e,
243
						true);
244
			}
245
		}
246
		return true;
247
	}
248

    
249
	public void saveModel(){
250
	    saveModel(true);
251
	}
252

    
253
	public void saveModel(boolean resetMerge){
254
	    //delete entities
255
	    for(Entry<T, DeleteConfiguratorBase> entry:toDelete.entrySet()){
256
	        try {
257
                delete(entry.getKey(), entry.getValue());
258
            } catch (ReferencedObjectUndeletableException e) {
259
                e.printStackTrace();
260
            }
261
	    }
262
	    if (!saveCandidates.isEmpty()){
263
	        CdmStore.getService(saveCandidates.iterator().next()).merge(new ArrayList<>(saveCandidates), true);
264
        }
265
	    if(resetMerge){
266
	        //merge entities
267
	        for(T mergeTarget:mergedEntities.keySet()){
268
	            for (T mergeCandidate: mergedEntities.get(mergeTarget)){
269
	                merge(mergeCandidate, mergeTarget);
270
	            }
271
	        }
272
	    }
273
	    toDelete.clear();
274
	    saveCandidates.clear();
275
	    mergedEntities.clear();
276
	}
277

    
278

    
279
	/** {@inheritDoc} */
280
	@Override
281
    public T create(T entity) {
282
		return save(entity);
283
	}
284

    
285
	public IEntityCreator<T> getEntityCreator(){
286
		if(entityCreator == null){
287
			entityCreator = createEntityCreator();
288
		}
289
		return entityCreator;
290
	}
291

    
292
	protected abstract IEntityCreator<T> createEntityCreator();
293

    
294
	/**
295
	 * The default implementation returns an empty list of sort providers.
296
	 * @return
297
	 */
298
	public List<IBulkEditorSortProvider<T>> getSortProviders(){
299
		List<IBulkEditorSortProvider<T>> sortProviders = new ArrayList<IBulkEditorSortProvider<T>>();
300

    
301
		sortProviders.add(new CdmBaseSortProvider<T>());
302

    
303
		return sortProviders;
304
	}
305

    
306
	/**
307
	 * Returns a textual representation given object. The default implementation
308
	 * in the abstract base class returns the simple name of the class, this may
309
	 * be overwritten to something more specific in subclasses.
310
	 *
311
	 * @param entity
312
	 * @return a textual representation given object.
313
	 */
314
	public String getTypeText(Object entity){
315
		return entity.getClass().getSimpleName();
316
	}
317

    
318
	public String getText(T entity) {
319
		if(entity instanceof IdentifiableEntity){
320
			IdentifiableEntity identifiableEntity = (IdentifiableEntity) HibernateProxyHelper.deproxy(entity);
321
			String text = identifiableEntity.getTitleCache();
322
			return text;
323
		}
324

    
325
		return "No text. Implement in subclass"; //$NON-NLS-1$
326
	}
327

    
328
	public BasicEventList<T> getModel() {
329
		return model;
330
	}
331

    
332
	public boolean replaceInModel(T entity) {
333
	    int index = model.indexOf(entity);
334
	    if(index >= 0) {
335
	        model.set(index, entity);
336
	        return true;
337
	    } else {
338
	        return false;
339
	    }
340
	}
341

    
342
    @Override
343
    public List<T> getRootEntities() {
344
        return getModel();
345
    }
346

    
347

    
348
    @Override
349
    public Map<Object, List<String>> getPropertyPathsMap() {
350
        // TODO Auto-generated method stub
351
        return null;
352
    }
353

    
354
	public ConversationHolder getConversation() {
355
		return conversation;
356
	}
357

    
358
	public Set<T> getSaveCandidates() {
359
        return saveCandidates;
360
    }
361

    
362
    public HashMap<T, Set<T>> getMergedEntities() {
363
        return mergedEntities;
364
    }
365

    
366
    public void setMergedEntities(HashMap<T, Set<T>> mergedEntities) {
367
        this.mergedEntities = mergedEntities;
368
    }
369
}
(1-1/11)