2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
9 package eu
.etaxonomy
.taxeditor
.bulkeditor
.input
;
11 import java
.util
.ArrayList
;
12 import java
.util
.Collections
;
13 import java
.util
.Comparator
;
14 import java
.util
.HashMap
;
15 import java
.util
.HashSet
;
16 import java
.util
.List
;
18 import java
.util
.Map
.Entry
;
20 import java
.util
.UUID
;
22 import org
.eclipse
.core
.runtime
.ICoreRunnable
;
23 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
24 import org
.eclipse
.core
.runtime
.jobs
.Job
;
26 import ca
.odell
.glazedlists
.BasicEventList
;
27 import eu
.etaxonomy
.cdm
.api
.conversation
.ConversationHolder
;
28 import eu
.etaxonomy
.cdm
.api
.service
.config
.DeleteConfiguratorBase
;
29 import eu
.etaxonomy
.cdm
.api
.service
.config
.IIdentifiableEntityServiceConfigurator
;
30 import eu
.etaxonomy
.cdm
.api
.service
.exception
.ReferencedObjectUndeletableException
;
31 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
32 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
33 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
34 import eu
.etaxonomy
.cdm
.model
.common
.MarkerType
;
35 import eu
.etaxonomy
.cdm
.strategy
.merge
.IMergable
;
36 import eu
.etaxonomy
.cdm
.strategy
.merge
.MergeException
;
37 import eu
.etaxonomy
.taxeditor
.annotatedlineeditor
.IEntityCreator
;
38 import eu
.etaxonomy
.taxeditor
.annotatedlineeditor
.IEntityPersistenceService
;
39 import eu
.etaxonomy
.taxeditor
.bulkeditor
.BulkEditorQuery
;
40 import eu
.etaxonomy
.taxeditor
.bulkeditor
.IBulkEditorSortProvider
;
41 import eu
.etaxonomy
.taxeditor
.bulkeditor
.input
.sortprovider
.CdmBaseSortProvider
;
42 import eu
.etaxonomy
.taxeditor
.bulkeditor
.input
.sortprovider
.TitleCacheComparator
;
43 import eu
.etaxonomy
.taxeditor
.bulkeditor
.internal
.TaxeditorBulkeditorPlugin
;
44 import eu
.etaxonomy
.taxeditor
.editor
.CdmEntitySessionInput
;
45 import eu
.etaxonomy
.taxeditor
.l10n
.Messages
;
46 import eu
.etaxonomy
.taxeditor
.model
.MessagingUtils
;
47 import eu
.etaxonomy
.taxeditor
.store
.CdmStore
;
55 public abstract class AbstractBulkEditorInput
<T
extends CdmBase
> extends CdmEntitySessionInput
implements
56 IEntityPersistenceService
<T
> {
58 private UUID entityUuid
;
60 private BasicEventList
<T
> model
= new BasicEventList
<>();
62 private Map
<T
, DeleteConfiguratorBase
> toDelete
= new HashMap
<>();
63 private List
<T
> saveCandidates
= new ArrayList
<>();
66 private Set
<T
> markedMergeCandidates
= new HashSet
<>();
67 private T markedMergeTarget
= null;
69 private HashMap
<T
, Set
<T
>> mergedEntities
= new HashMap
<>();
71 private IEntityCreator
<T
> entityCreator
;
72 private final ConversationHolder conversation
;
74 private Job searchJob
;
76 public AbstractBulkEditorInput() {
78 this.conversation
= CdmStore
.createConversation();
81 static public AbstractBulkEditorInput
NewInstance(BulkEditorInputType inputType
) {
83 return BulkEditorInputType
.getInput(inputType
);
86 public static AbstractBulkEditorInput
NewInstance(IdentifiableEntity entity
) {
88 BulkEditorInputType inputType
= BulkEditorInputType
.getByType(entity
.getClass());
90 AbstractBulkEditorInput editorInput
= NewInstance(inputType
);
92 editorInput
.setEntityUuid(entity
.getUuid());
97 public abstract String
getName();
99 public String
getEditorName(){
103 protected abstract List
<T
> listEntities(IIdentifiableEntityServiceConfigurator configurator
);
105 protected abstract T
loadEntity(UUID entityUuid
);
107 public void setMergeTarget(T t
){
108 markedMergeTarget
= t
;
111 public Set
<T
> getMergeCandidates() {
112 return markedMergeCandidates
;
115 public T
getMergeTarget() {
116 return markedMergeTarget
;
119 public void removeMergeTarget(){
120 markedMergeTarget
= null;
123 public void addMergeCandidate(T t
){
124 markedMergeCandidates
.add(t
);
127 public void removeMergeCandidate(T t
){
128 markedMergeCandidates
.remove(t
);
131 public void addToDelete(T t
, DeleteConfiguratorBase config
) {
132 toDelete
.put(t
, config
);
134 public void addSaveCandidate(T t
){
135 saveCandidates
.add(t
);
137 private void setEntityUuid(UUID entityUuid
){
138 this.entityUuid
= entityUuid
;
141 public UUID
getEntityUuid() {
145 public void performSearch(final BulkEditorQuery bulkEditorQuery
) {
146 if(searchJob
!=null && searchJob
.getState()!=Job
.NONE
){
147 MessagingUtils
.informationDialog(Messages
.AbstractBulkEditorInput_MULTIPLE_SEARCH_TITLE
, Messages
.AbstractBulkEditorInput_MULTIPLE_SEARCH_MESSAGE
);
152 if(getEntityUuid() != null){
154 T entity
= loadEntity(getEntityUuid());
157 else if(bulkEditorQuery
!= null){
159 IIdentifiableEntityServiceConfigurator configurator
= bulkEditorQuery
.getSearchConfigurator();
160 Comparator queryComparator
= (bulkEditorQuery
.getComparator() != null) ? bulkEditorQuery
.getComparator() : new TitleCacheComparator();
162 String jobLabel
= Messages
.AbstractBulkEditorInput_LOADING
+getName();
163 searchJob
= Job
.create(jobLabel
, (ICoreRunnable
) monitor
-> {
164 monitor
.beginTask(jobLabel
, IProgressMonitor
.UNKNOWN
);
168 if (monitor
.isCanceled()) {
171 configurator
.setPageNumber(pageNumber
);
172 entities
= listEntities(configurator
);
173 model
.addAll(entities
);
175 Collections
.sort(model
, queryComparator
);
176 } while (!entities
.isEmpty());
179 searchJob
.schedule();
183 public boolean isMergingEnabled() {
187 public boolean isConvertingEnabled() {
191 public boolean isMarkerTypeEditingEnabled(MarkerType markerType
) {
198 public boolean merge(T entity
, T mergeTarget
) {
199 if (entity
instanceof IMergable
) {
201 CdmStore
.getCommonService().merge(mergeTarget
.getUuid(), entity
.getUuid(), (Class
<?
extends CdmBase
>)entity
.getClass());
202 } catch (MergeException e
) {
203 MessagingUtils
.errorDialog(Messages
.AbstractBulkEditorInput_MERGE_ERROR_TITLE
,
205 String
.format(Messages
.AbstractBulkEditorInput_MERGE_ERROR_MESSAGE
, entity
.getClass().getName()),
206 TaxeditorBulkeditorPlugin
.PLUGIN_ID
,
214 public void saveModel(){
218 public void saveModel(boolean resetMerge
){
220 for(Entry
<T
, DeleteConfiguratorBase
> entry
:toDelete
.entrySet()){
222 delete(entry
.getKey(), entry
.getValue());
223 } catch (ReferencedObjectUndeletableException e
) {
228 if (!saveCandidates
.isEmpty()){
229 CdmStore
.getService(saveCandidates
.get(0)).merge(saveCandidates
, true);
233 for(T mergeTarget
:mergedEntities
.keySet()){
234 for (T mergeCandidate
: mergedEntities
.get(mergeTarget
)){
235 merge(mergeCandidate
, mergeTarget
);
238 mergedEntities
.clear();
246 public T
create(T entity
) {
250 public IEntityCreator
<T
> getEntityCreator(){
251 if(entityCreator
== null){
252 entityCreator
= createEntityCreator();
254 return entityCreator
;
257 protected abstract IEntityCreator
<T
> createEntityCreator();
260 * The default implementation returns an empty list of sort providers.
263 public List
<IBulkEditorSortProvider
<T
>> getSortProviders(){
264 List
<IBulkEditorSortProvider
<T
>> sortProviders
= new ArrayList
<IBulkEditorSortProvider
<T
>>();
266 sortProviders
.add(new CdmBaseSortProvider
<T
>());
268 return sortProviders
;
272 * Returns a textual representation given object. The default implementation
273 * in the abstract base class returns the simple name of the class, this may
274 * be overwritten to something more specific in subclasses.
277 * @return a textual representation given object.
279 public String
getTypeText(Object entity
){
280 return entity
.getClass().getSimpleName();
283 public String
getText(T entity
) {
284 if(entity
instanceof IdentifiableEntity
){
285 IdentifiableEntity identifiableEntity
= (IdentifiableEntity
) HibernateProxyHelper
.deproxy(entity
);
286 String text
= ""; //$NON-NLS-1$
287 if(markedMergeCandidates
.contains(entity
)){
288 text
+= Messages
.AbstractBulkEditorInput_CANDIDATE
;
290 else if(markedMergeTarget
==entity
){
291 text
+= Messages
.AbstractBulkEditorInput_TARGET
;
293 text
+= identifiableEntity
.getTitleCache();
297 return "No text. Implement in subclass"; //$NON-NLS-1$
300 public BasicEventList
<T
> getModel() {
304 protected boolean replaceInModel(T entity
) {
305 int index
= model
.indexOf(entity
);
307 model
.set(index
, entity
);
315 public List
<T
> getRootEntities() {
321 public Map
<Object
, List
<String
>> getPropertyPathsMap() {
322 // TODO Auto-generated method stub
326 public ConversationHolder
getConversation() {
330 public List
<T
> getSaveCandidates() {
331 return saveCandidates
;
337 public void resetSaveCandidates() {
338 this.saveCandidates
.clear();
342 public HashMap
<T
, Set
<T
>> getMergedEntities() {
343 return mergedEntities
;
346 public void setMergedEntities(HashMap
<T
, Set
<T
>> mergedEntities
) {
347 this.mergedEntities
= mergedEntities
;