ref #7699: wait for the thread to stop
[taxeditor.git] / eu.etaxonomy.taxeditor.bulkeditor / src / main / java / eu / etaxonomy / taxeditor / bulkeditor / input / AbstractBulkEditorInput.java
index b31a10377a86fcc80e343665d4cc0f6f430fec49..747dc3df644b3d366599870eb49a169cda42dc6f 100644 (file)
@@ -9,6 +9,7 @@
 package eu.etaxonomy.taxeditor.bulkeditor.input;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -17,6 +18,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 import java.util.UUID;
+import java.util.stream.Collectors;
 
 import org.eclipse.core.runtime.ICoreRunnable;
 import org.eclipse.core.runtime.jobs.Job;
@@ -31,6 +33,7 @@ import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
 import eu.etaxonomy.cdm.model.common.CdmBase;
 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
 import eu.etaxonomy.cdm.model.common.MarkerType;
+import eu.etaxonomy.cdm.persistence.dto.MergeResult;
 import eu.etaxonomy.cdm.strategy.merge.IMergable;
 import eu.etaxonomy.cdm.strategy.merge.MergeException;
 import eu.etaxonomy.taxeditor.annotatedlineeditor.IEntityCreator;
@@ -50,18 +53,27 @@ import eu.etaxonomy.taxeditor.store.CdmStore;
 /**
  * @author p.ciardelli
  * @created 25.06.2009
- * @version 1.0
- * @param <T>
  */
-public abstract class AbstractBulkEditorInput<T extends CdmBase> extends CdmEntitySessionInput implements
-    IEntityPersistenceService<T> {
+public abstract class AbstractBulkEditorInput<T extends CdmBase>
+        extends CdmEntitySessionInput
+        implements IEntityPersistenceService<T> {
+
+
+    private static final String PROPERTY_PROTECTED_TITLECACHE = "Protect TitleCache";
+    private static final String TYPE_PROPERTY = Messages.BulkEditorE4_TYPE;
+    private static final String ID_PROPERTY = "Id"; //$NON-NLS-1$
+    private static final String UUID_PROPERTY = "Uuid"; //$NON-NLS-1$
 
        private UUID entityUuid;
 
        private BasicEventList<T> model = new BasicEventList<>();
 
        private Map<T, DeleteConfiguratorBase> toDelete = new HashMap<>();
-       private Set<T> saveCandidates = new HashSet<>();
+       public Map<T, DeleteConfiguratorBase> getToDelete() {
+        return toDelete;
+    }
+
+    private Set<T> saveCandidates = new HashSet<>();
 
 
        private Set<T> markedMergeCandidates = new HashSet<>();
@@ -88,13 +100,24 @@ public abstract class AbstractBulkEditorInput<T extends CdmBase> extends CdmEnti
 
                BulkEditorInputType inputType = BulkEditorInputType.getByType(entity.getClass());
 
-               AbstractBulkEditorInput editorInput = NewInstance(inputType);
+               AbstractBulkEditorInput<?> editorInput = NewInstance(inputType);
 
                editorInput.setEntityUuid(entity.getUuid());
 
                return editorInput;
        }
 
+       public static AbstractBulkEditorInput NewInstance(Class clazz, UUID uuid) {
+
+        BulkEditorInputType inputType = BulkEditorInputType.getByType(clazz);
+
+        AbstractBulkEditorInput<?> editorInput = NewInstance(inputType);
+
+        editorInput.setEntityUuid(uuid);
+
+        return editorInput;
+    }
+
     public abstract String getName();
 
     public String getEditorName(){
@@ -111,8 +134,56 @@ public abstract class AbstractBulkEditorInput<T extends CdmBase> extends CdmEnti
 
        protected abstract T loadEntity(UUID entityUuid);
 
-       public Comparator<T> getTitleComparator(){
-           return new TitleCacheComparator();
+    public List<String> getPropertyKeys(){
+        List<String> properties = new ArrayList<>();
+        properties.add(getName());
+        properties.add(PROPERTY_PROTECTED_TITLECACHE);
+        properties.addAll(getPropertyKeys_internal());
+        properties.add(TYPE_PROPERTY);
+        properties.add(ID_PROPERTY);
+        properties.add(UUID_PROPERTY);
+        return properties;
+    }
+
+    protected abstract List<String> getPropertyKeys_internal();
+
+
+    public Object getPropertyValue(T cdmBase, String property){
+        if(property.equals(getName())){
+            return getText(cdmBase);
+        }
+        else if(property.equals(PROPERTY_PROTECTED_TITLECACHE)
+                &&cdmBase.isInstanceOf(IdentifiableEntity.class)){
+            return HibernateProxyHelper.deproxy(cdmBase, IdentifiableEntity.class).isProtectedTitleCache();
+        }
+        else if(property.equals(TYPE_PROPERTY)){
+            return getTypeText(cdmBase);
+        }
+        else if(property.equals(UUID_PROPERTY)){
+            return cdmBase.getUuid();
+        }
+        else if(property.equals(ID_PROPERTY)){
+            return cdmBase.getId();
+        }
+        return null;
+    }
+
+    public boolean isBooleanProperty(String property) {
+        if(property.equals(PROPERTY_PROTECTED_TITLECACHE)){
+            return true;
+        }
+        return false;
+    }
+
+    public boolean isCacheProperty(String property) {
+        if(property.equals(PROPERTY_PROTECTED_TITLECACHE)){
+            return true;
+        }
+        return false;
+    }
+
+       public <T extends IdentifiableEntity> Comparator<T> getTitleComparator(){
+           return new TitleCacheComparator<T>();
        }
 
        public void setMergeTarget(T t){
@@ -145,7 +216,7 @@ public abstract class AbstractBulkEditorInput<T extends CdmBase> extends CdmEnti
     public void addSaveCandidate(T t){
         saveCandidates.add(t);
     }
-       private void setEntityUuid(UUID entityUuid){
+       public void setEntityUuid(UUID entityUuid){
                this.entityUuid = entityUuid;
        }
 
@@ -156,18 +227,39 @@ public abstract class AbstractBulkEditorInput<T extends CdmBase> extends CdmEnti
        public void performSearch(final BulkEditorQuery bulkEditorQuery, IStructuredSelection selection) {
            //cancel previous search job
            if(searchJob!=null && searchJob.getState()!=Job.NONE){
-               searchJob.cancel();
+               boolean isCanceled = searchJob.cancel();
+               if (!isCanceled){
+                   while (!isCanceled){
+                   try {
+                       Thread.sleep(200);
+                   } catch (InterruptedException e) {
+                   }
+                   isCanceled = searchJob.cancel();
+                   }
+               }
                searchJob = null;
+//             /*
+//              * wait for a little while for the job to finish
+//              * to avoid asynchronously loaded results of the
+//              * previous search being shown in the next search
+//              * (not critical but explicitly waiting for the job to finish
+//              * could run into an endless loop by mistake)
+//              */
+//             try {
+//                Thread.sleep(500);
+//            } catch (InterruptedException e) {
+//            }
            }
-           model.clear();
+        model.clear();
+        markedMergeCandidates.clear();
+        markedMergeTarget = null;
 
                if(getEntityUuid() != null){
-
                        T entity = loadEntity(getEntityUuid());
                        model.add(entity);
                }
                else if(bulkEditorQuery != null){
-            IIdentifiableEntityServiceConfigurator configurator = bulkEditorQuery.getSearchConfigurator();
+            IIdentifiableEntityServiceConfigurator<?> configurator = bulkEditorQuery.getSearchConfigurator();
 
             // check for UUID search
             String titleSearchString = configurator.getTitleSearchString();
@@ -191,22 +283,32 @@ public abstract class AbstractBulkEditorInput<T extends CdmBase> extends CdmEnti
                    monitor.beginTask(jobLabel, totalWork);
                    int pageNumber = 0;
                    List<T> entities;
+
+                   //load previously selected element
+                   UUID selectedUuid = null;
+                   if(selection!=null && selection.getFirstElement() instanceof CdmBase){
+                       selectedUuid = ((CdmBase) selection.getFirstElement()).getUuid();
+                       T entity = loadEntity(selectedUuid);
+                       model.add(entity);
+                   }
+
                 do {
                     if (monitor.isCanceled()) {
                         break;
                     }
                     configurator.setPageNumber(pageNumber);
                     entities = listEntities(configurator);
-                    model.addAll(entities);
-                    //select if entity is loaded
-                    if(selection!=null && model.containsAll(selection.toList())){
-                        EventUtility.postAsyncEvent(WorkbenchEventConstants.BULK_EDITOR_SEARCH_FINISHED, selection);
-                    }
+
+                    addToModel(entities, selectedUuid);
+
                     pageNumber++;
                     monitor.worked(pageSize);
                     long workedLong = pageSize*pageNumber;
                     int loadedCount =  workedLong>Integer.MAX_VALUE?Integer.MAX_VALUE:(int)workedLong;
                     monitor.setTaskName(String.format(Messages.AbstractBulkEditorInput_LOADED, loadedCount, totalWork, getName()));
+
+                    //Update selection
+                    EventUtility.postAsyncEvent(WorkbenchEventConstants.BULK_EDITOR_SEARCH_FINISHED, selection);
                 } while (!entities.isEmpty());
                    monitor.done();
                    EventUtility.postAsyncEvent(WorkbenchEventConstants.BULK_EDITOR_SEARCH_FINISHED, selection);
@@ -215,6 +317,22 @@ public abstract class AbstractBulkEditorInput<T extends CdmBase> extends CdmEnti
                }
        }
 
+    private void addToModel(List<T> entities, UUID selectedUuid){
+           //filter pre-loaded previously selected element
+           if(selectedUuid!=null){
+               entities = entities.stream().filter(entity->!entity.getUuid().equals(selectedUuid)).collect(Collectors.toList());
+           }
+           /*
+         * IMPORTANT!
+         * Entities have to be loaded into the main session because they are
+         * loaded in a parallel asynchronous thread
+         */
+        if(getCdmEntitySession()!=null){//is null when closing the bulk editor during loading
+            getCdmEntitySession().load(entities, true);
+        }
+        model.addAll(entities);
+       }
+
        public boolean isMergingEnabled() {
                return false;
        }
@@ -227,8 +345,6 @@ public abstract class AbstractBulkEditorInput<T extends CdmBase> extends CdmEnti
                return false;
        }
 
-
-       /** {@inheritDoc} */
        @Override
     public boolean merge(T entity, T mergeTarget) {
                if (entity instanceof IMergable) {
@@ -260,7 +376,12 @@ public abstract class AbstractBulkEditorInput<T extends CdmBase> extends CdmEnti
             }
            }
            if (!saveCandidates.isEmpty()){
-               CdmStore.getService(saveCandidates.iterator().next()).merge(new ArrayList<>(saveCandidates), true);
+               List<MergeResult<T>> results = CdmStore.getService(saveCandidates.iterator().next()).merge(new ArrayList<>(saveCandidates), true);
+               for (MergeResult<T> result: results){
+                   if (result.getMergedEntity() != null){
+                       T entity = result.getMergedEntity();
+                   }
+               }
         }
            if(resetMerge){
                //merge entities
@@ -275,8 +396,6 @@ public abstract class AbstractBulkEditorInput<T extends CdmBase> extends CdmEnti
            mergedEntities.clear();
        }
 
-
-       /** {@inheritDoc} */
        @Override
     public T create(T entity) {
                return save(entity);
@@ -296,9 +415,9 @@ public abstract class AbstractBulkEditorInput<T extends CdmBase> extends CdmEnti
         * @return
         */
        public List<IBulkEditorSortProvider<T>> getSortProviders(){
-               List<IBulkEditorSortProvider<T>> sortProviders = new ArrayList<IBulkEditorSortProvider<T>>();
+               List<IBulkEditorSortProvider<T>> sortProviders = new ArrayList<>();
 
-               sortProviders.add(new CdmBaseSortProvider<T>());
+               sortProviders.add(new CdmBaseSortProvider<>());
 
                return sortProviders;
        }
@@ -316,8 +435,8 @@ public abstract class AbstractBulkEditorInput<T extends CdmBase> extends CdmEnti
        }
 
        public String getText(T entity) {
-               if(entity instanceof IdentifiableEntity){
-                       IdentifiableEntity identifiableEntity = (IdentifiableEntity) HibernateProxyHelper.deproxy(entity);
+               if(entity.isInstanceOf(IdentifiableEntity.class)){
+                       IdentifiableEntity<?> identifiableEntity = HibernateProxyHelper.deproxy(entity, IdentifiableEntity.class);
                        String text = identifiableEntity.getTitleCache();
                        return text;
                }
@@ -340,7 +459,7 @@ public abstract class AbstractBulkEditorInput<T extends CdmBase> extends CdmEnti
        }
 
     @Override
-    public List<T> getRootEntities() {
+    public Collection<T> getRootEntities() {
         return getModel();
     }
 
@@ -366,4 +485,5 @@ public abstract class AbstractBulkEditorInput<T extends CdmBase> extends CdmEnti
     public void setMergedEntities(HashMap<T, Set<T>> mergedEntities) {
         this.mergedEntities = mergedEntities;
     }
+
 }