Project

General

Profile

Download (10.3 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

    
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
}
(1-1/11)