commit fe7f013171b071f35f93c19c0c67bd46a52eba8b
Author: Patrick Plitzner <p.plitzner@bgbm.org>
Date:   Wed Oct 26 14:56:31 2016 +0200

    ref #5458 Use service based on UuidAndTitleCache to build taxon tree

diff --git a/src/main/java/eu/etaxonomy/cdm/vaadin/container/TaxonNodeContainer.java b/src/main/java/eu/etaxonomy/cdm/vaadin/container/TaxonNodeContainer.java
index f5fd43d3..d78b81ac 100644
--- a/src/main/java/eu/etaxonomy/cdm/vaadin/container/TaxonNodeContainer.java
+++ b/src/main/java/eu/etaxonomy/cdm/vaadin/container/TaxonNodeContainer.java
@@ -1,23 +1,25 @@
 package eu.etaxonomy.cdm.vaadin.container;
 
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collection;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import com.vaadin.data.Item;
 import com.vaadin.data.util.HierarchicalContainer;
 
 import eu.etaxonomy.cdm.api.service.IClassificationService;
-import eu.etaxonomy.cdm.model.name.Rank;
 import eu.etaxonomy.cdm.model.taxon.Classification;
 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
+import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
 import eu.etaxonomy.cdm.vaadin.util.CdmSpringContextHelper;
 
 public class TaxonNodeContainer extends HierarchicalContainer {
 
 	private static final long serialVersionUID = 102401340698963360L;
-	public static final String LABEL = "label";
+	public static final String LABEL = "titleCache";
+	private Set<Object> itemCache = new HashSet<Object>();
+
 
 	private final List<String> nodeInitStrategy = Arrays.asList(new String[]{
 	        "taxon.sec",
@@ -30,7 +32,7 @@ public class TaxonNodeContainer extends HierarchicalContainer {
 	 * @param parentNode the parent node which will <b>not</b> be included
 	 * in the result but only its child nodes
 	 */
-	public TaxonNodeContainer(TaxonNode parentNode) {
+	public TaxonNodeContainer(UuidAndTitleCache<TaxonNode> parentNode) {
 		addContainerProperty(LABEL, String.class, "[no taxon]");
 		if(parentNode==null){
             //just load classifications
@@ -47,83 +49,30 @@ public class TaxonNodeContainer extends HierarchicalContainer {
 		else{
 		    addItem(parentNode);
 		}
-//		getTaxonNodeList(parentNode);
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
 	@Override
-	public Collection<?> getChildren(Object itemId) {
-	    List<TaxonNode> childNodes = ((TaxonNode) itemId).getChildNodes();
-	    for (TaxonNode taxonNode : childNodes) {
-            if(!containsId(taxonNode)){
-                setParent(taxonNode, itemId);
-            }
+	public Item addItem(Object itemId) {
+	    if(itemId instanceof UuidAndTitleCache){
+	        if(!itemCache.contains(((UuidAndTitleCache<TaxonNode>) itemId).getId())){
+	            return super.addItem(itemId);
+	        }
+        } else {
+            return super.addItem(itemId);
         }
-        return childNodes;
+	    return null;
 	}
 
 	/**
 	 * {@inheritDoc}
 	 */
 	@Override
-	public Object getParent(Object itemId) {
-	    return ((TaxonNode) itemId).getParent();
-	}
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean hasChildren(Object itemId) {
-        return !((TaxonNode)itemId).getChildNodes().isEmpty();
-    }
-
-	public void getTaxonNodeList(TaxonNode parentNode) {
-		List<TaxonNode> nodes = new ArrayList<TaxonNode>();
-
-
-		if(parentNode==null){
-			//just load classifications
-			IClassificationService classificationService = CdmSpringContextHelper.getClassificationService();
-			List<Classification> classificationList = classificationService.listClassifications(null, null, null, nodeInitStrategy);
-			for (Classification classification : classificationList) {
-			    TaxonNode rootNode = classification.getRootNode();
-			    Item item = addItem(rootNode);
-				setChildrenAllowed(rootNode, false);
-				nodes.add(rootNode);
-                if(rootNode.getClassification()!=null){
-                    item.getItemProperty(LABEL).setValue(rootNode.getClassification().getName().getText());
-                }
-			}
-		}
-		else{
-			//load child nodes
-	        addChildNodes(parentNode);
-		}
-	}
-
-	private void addChildNodes(TaxonNode parentNode) {
-		List<TaxonNode> childNodes = parentNode.getChildNodes();
-		setChildrenAllowed(parentNode, !childNodes.isEmpty());
-		boolean hasValidChildren = false;
-		for (TaxonNode taxonNode : childNodes) {
-			if(taxonNode!=null && taxonNode.getTaxon()!=null && taxonNode.getTaxon().getName()!=null){
-				Rank rank = taxonNode.getTaxon().getName().getRank();
-				if(rank!=null && rank.isHigher(Rank.SPECIES())){
-				    Item item = addItem(taxonNode);
-					setParent(taxonNode, parentNode);
-					if(taxonNode.getTaxon()!=null){
-					    item.getItemProperty(LABEL).setValue(taxonNode.getTaxon().getName().getTitleCache());
-					}
-					else if(taxonNode.getClassification()!=null){
-                        item.getItemProperty(LABEL).setValue(taxonNode.getClassification().getName().getText());
-                    }
-					hasValidChildren = true;
-
-					addChildNodes(taxonNode);
-				}
-			}
-		}
-		setChildrenAllowed(parentNode, hasValidChildren);
+	public boolean setParent(Object itemId, Object newParentId) {
+	    itemCache.add(((UuidAndTitleCache<TaxonNode>) itemId).getId());;
+	    return super.setParent(itemId, newParentId);
 	}
 
 }
diff --git a/src/main/java/eu/etaxonomy/cdm/vaadin/container/TaxonTreeContainer.java b/src/main/java/eu/etaxonomy/cdm/vaadin/container/TaxonTreeContainer.java
deleted file mode 100644
index b007342d..00000000
--- a/src/main/java/eu/etaxonomy/cdm/vaadin/container/TaxonTreeContainer.java
+++ /dev/null
@@ -1,140 +0,0 @@
-// $Id$
-/**
-* Copyright (C) 2016 EDIT
-* European Distributed Institute of Taxonomy
-* http://www.e-taxonomy.eu
-*
-* The contents of this file are subject to the Mozilla Public License Version 1.1
-* See LICENSE.TXT at the top of this package for the full license terms.
-*/
-package eu.etaxonomy.cdm.vaadin.container;
-
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-
-import com.vaadin.data.Container.Hierarchical;
-import com.vaadin.data.util.filter.Compare;
-import com.vaadin.data.util.sqlcontainer.RowId;
-
-import eu.etaxonomy.cdm.model.taxon.TaxonNode;
-import eu.etaxonomy.cdm.vaadin.util.CdmQueryFactory;
-
-/**
- * @author pplitzner
- * @date 18.10.2016
- *
- */
-public class TaxonTreeContainer extends CdmSQLContainer implements Hierarchical{
-
-    private static final long serialVersionUID = 5488629563366944491L;
-
-    private final Collection<RowId> rootItemIds = new HashSet<>();
-    private final Map<Object, List<Object>> parentChildMap = new HashMap<>();
-    private final Map<Object, Object> childParentMap = new HashMap<>();
-    private CdmSQLContainer childrenContainer;
-
-    public TaxonTreeContainer(TaxonNode parentNode) throws SQLException {
-        super(CdmQueryFactory.generateTaxonTreeQuery("Name", Integer.toString(parentNode.getClassification().getId())));
-        childrenContainer = new CdmSQLContainer(CdmQueryFactory.generateTaxonTreeQuery("Name", Integer.toString(parentNode.getClassification().getId())));
-        List<TaxonNode> childNodes = parentNode.getChildNodes();
-        for (TaxonNode taxonNode : childNodes) {
-            rootItemIds.add(new RowId(taxonNode.getId()));
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Collection<?> getChildren(Object itemId) {
-        List<Object> children = parentChildMap.get(itemId);
-        if(children==null){
-            children = updateChildren(itemId);
-        }
-        return children;
-    }
-
-    private List<Object> updateChildren(Object itemId) {
-        List<Object> children;
-        Filter childrenOfTaxonFilter = new Compare.Equal("tn.parent_id", Integer.valueOf(itemId.toString()));
-        childrenContainer.addContainerFilter(childrenOfTaxonFilter);
-        children = new ArrayList<>();
-        Collection<?> itemIds = childrenContainer.getItemIds();
-        for (Object object : itemIds) {
-            childParentMap.put(object, itemId);
-            children.add(object);
-        }
-        childrenContainer.removeAllContainerFilters();
-
-        parentChildMap.put(itemId, children);
-        return children;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Object getParent(Object itemId) {
-        return childParentMap.get(itemId);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean hasChildren(Object itemId) {
-        List<Object> children = parentChildMap.get(itemId);
-        if(children==null){
-            children = updateChildren(itemId);
-        }
-        return !children.isEmpty();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Collection<?> rootItemIds() {
-        return rootItemIds;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean setParent(Object itemId, Object newParentId) throws UnsupportedOperationException {
-        return true;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean areChildrenAllowed(Object itemId) {
-        return hasChildren(itemId);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean setChildrenAllowed(Object itemId, boolean areChildrenAllowed) throws UnsupportedOperationException {
-        return true;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean isRoot(Object itemId) {
-        return itemId==null?true:rootItemIds.contains(itemId);
-    }
-
-
-
-}
diff --git a/src/main/java/eu/etaxonomy/cdm/vaadin/view/dbstatus/DistributionSettingsConfigWindow.java b/src/main/java/eu/etaxonomy/cdm/vaadin/view/dbstatus/DistributionSettingsConfigWindow.java
index 3178b94b..7f355e36 100644
--- a/src/main/java/eu/etaxonomy/cdm/vaadin/view/dbstatus/DistributionSettingsConfigWindow.java
+++ b/src/main/java/eu/etaxonomy/cdm/vaadin/view/dbstatus/DistributionSettingsConfigWindow.java
@@ -1,17 +1,19 @@
 // $Id$
 /**
-* Copyright (C) 2015 EDIT
-* European Distributed Institute of Taxonomy
-* http://www.e-taxonomy.eu
-*
-* The contents of this file are subject to the Mozilla Public License Version 1.1
-* See LICENSE.TXT at the top of this package for the full license terms.
-*/
+ * Copyright (C) 2015 EDIT
+ * European Distributed Institute of Taxonomy
+ * http://www.e-taxonomy.eu
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * See LICENSE.TXT at the top of this package for the full license terms.
+ */
 package eu.etaxonomy.cdm.vaadin.view.dbstatus;
 
-import java.sql.SQLException;
+import java.util.Collection;
 import java.util.Set;
+import java.util.UUID;
 
+import com.vaadin.data.Item;
 import com.vaadin.data.Property;
 import com.vaadin.data.Property.ValueChangeEvent;
 import com.vaadin.data.Property.ValueChangeListener;
@@ -25,15 +27,18 @@ import com.vaadin.ui.ComboBox;
 import com.vaadin.ui.HorizontalLayout;
 import com.vaadin.ui.ListSelect;
 import com.vaadin.ui.Table.ColumnHeaderMode;
+import com.vaadin.ui.Tree.ExpandEvent;
+import com.vaadin.ui.Tree.ExpandListener;
 import com.vaadin.ui.TreeTable;
 import com.vaadin.ui.VerticalLayout;
 
+import eu.etaxonomy.cdm.model.common.CdmBase;
 import eu.etaxonomy.cdm.model.common.TermVocabulary;
 import eu.etaxonomy.cdm.model.location.NamedArea;
 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
+import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
 import eu.etaxonomy.cdm.vaadin.container.NamedAreaContainer;
 import eu.etaxonomy.cdm.vaadin.container.TaxonNodeContainer;
-import eu.etaxonomy.cdm.vaadin.container.TaxonTreeContainer;
 import eu.etaxonomy.cdm.vaadin.util.CdmSpringContextHelper;
 import eu.etaxonomy.cdm.vaadin.util.DistributionEditorUtil;
 
@@ -42,10 +47,10 @@ import eu.etaxonomy.cdm.vaadin.util.DistributionEditorUtil;
  * @author pplitzner
  *
  */
-public class DistributionSettingsConfigWindow extends AbstractSettingsDialogWindow implements ValueChangeListener, ClickListener{
+public class DistributionSettingsConfigWindow extends AbstractSettingsDialogWindow implements ValueChangeListener, ClickListener, ExpandListener{
 
-	private static final long serialVersionUID = 1439411115014088780L;
-	private ComboBox classificationBox;
+    private static final long serialVersionUID = 1439411115014088780L;
+    private ComboBox classificationBox;
     private ComboBox distAreaBox;
     private ListSelect namedAreaList;
     private TreeTable taxonTree;
@@ -58,45 +63,47 @@ public class DistributionSettingsConfigWindow extends AbstractSettingsDialogWind
      * @param distributionTableView
      */
     public DistributionSettingsConfigWindow(DistributionTableView distributionTableView) {
-    	super();
+        super();
     }
 
+    @Override
     protected void init() {
-    	//init classification and taxon selection
+        //init classification and taxon selection
         TaxonNode chosenTaxonNode = presenter.getChosenTaxonNode();
 
         classificationBox.setContainerDataSource(new TaxonNodeContainer(null));
         Object classificationSelection = null;
-		if(classificationBox.getItemIds().size()==1){
-			//only one classification exists
-		    classificationSelection = classificationBox.getItemIds().iterator().next();
-		}
-		else if(chosenTaxonNode!=null){
-			//get the classification from the selected taxon node
-			classificationSelection = chosenTaxonNode.getClassification().getRootNode();
-		}
+        if(classificationBox.getItemIds().size()==1){
+            //only one classification exists
+            classificationSelection = classificationBox.getItemIds().iterator().next();
+        }
+        else if(chosenTaxonNode!=null){
+            //get the classification from the selected taxon node
+            classificationSelection = chosenTaxonNode.getClassification().getRootNode();
+        }
         if(classificationSelection!=null){
-        	classificationBox.setValue(classificationSelection);
-        	try {
-                taxonTree.setContainerDataSource(new TaxonTreeContainer((TaxonNode) classificationSelection));
-                taxonTree.setVisibleColumns("Name");
-            } catch (SQLException e) {
-    			DistributionEditorUtil.showSqlError(e);
+            classificationBox.setValue(classificationSelection);
+            taxonTree.addExpandListener(this);
+
+            UUID uuid = ((CdmBase) classificationSelection).getUuid();
+            int id = ((CdmBase) classificationSelection).getId();
+            String titleCache = ((TaxonNode) classificationSelection).getClassification().getTitleCache();
+            UuidAndTitleCache<TaxonNode> parent = new UuidAndTitleCache<>(uuid, id, titleCache);
+            taxonTree.setContainerDataSource(new TaxonNodeContainer(parent));
+            if(chosenTaxonNode!=null){
+                taxonTree.select(new RowId(chosenTaxonNode.getId()));
             }
-        	if(chosenTaxonNode!=null){
-    			taxonTree.select(new RowId(chosenTaxonNode.getId()));
-        	}
         }
         classificationBox.addValueChangeListener(this);
-        
+
         TermVocabulary<NamedArea> chosenArea = presenter.getChosenArea();
         distAreaBox.setContainerDataSource(presenter.getDistributionContainer());
         distAreaBox.setValue(chosenArea);
         distAreaBox.addValueChangeListener(this);
 
         if(chosenArea!=null){
-        	NamedAreaContainer container = new NamedAreaContainer(chosenArea);
-        	namedAreaList.setContainerDataSource(container);
+            NamedAreaContainer container = new NamedAreaContainer(chosenArea);
+            namedAreaList.setContainerDataSource(container);
         }
         Object selectedAreas = VaadinSession.getCurrent().getAttribute(DistributionEditorUtil.SATTR_SELECTED_AREAS);
         namedAreaList.setValue(selectedAreas);
@@ -106,12 +113,13 @@ public class DistributionSettingsConfigWindow extends AbstractSettingsDialogWind
         updateButtons();
     }
 
+    @Override
     protected AbstractLayout buildMainLayout() {
 
         mainLayout = new VerticalLayout();
         mainLayout.setSizeFull();
 
-    	HorizontalLayout leftAndRightContainer = new HorizontalLayout();
+        HorizontalLayout leftAndRightContainer = new HorizontalLayout();
         leftAndRightContainer.setImmediate(false);
         leftAndRightContainer.setSizeFull();
         leftAndRightContainer.setMargin(true);
@@ -186,58 +194,73 @@ public class DistributionSettingsConfigWindow extends AbstractSettingsDialogWind
         return leftAndRightContainer;
     }
 
-	@Override
-	public void valueChange(ValueChangeEvent event) {
-		Property property = event.getProperty();
-		if(property==classificationBox){
-			TaxonNode parentNode = (TaxonNode) event.getProperty().getValue();
-			if(parentNode!=null){
-			    try {
-                    taxonTree.setContainerDataSource(new TaxonTreeContainer(parentNode));
-                    taxonTree.setVisibleColumns("Name");
-                } catch (SQLException e) {
-        			DistributionEditorUtil.showSqlError(e);
-                }
-			}
-			else{
-				taxonTree.setContainerDataSource(null);
-			}
-		}
-
-		else if(property==distAreaBox){
-			TermVocabulary<NamedArea> vocabulary = (TermVocabulary<NamedArea>) event.getProperty().getValue();
-			NamedAreaContainer container = new NamedAreaContainer(vocabulary);
-			namedAreaList.setContainerDataSource(container);
-		}
-		updateButtons();
-	}
-	
-	@Override
-	protected boolean isValid() {
-		return classificationBox.getValue()!=null && distAreaBox.getValue()!=null;
-	}
-
-	@Override
-	public void buttonClick(ClickEvent event) {
-		Object source = event.getSource();
-		if(source==okButton){
-			TaxonNode taxonNode = null;
-			TermVocabulary<NamedArea> term = null;
-			//TODO use field converter
-			if(taxonTree.getValue()!=null){
-			    taxonNode = CdmSpringContextHelper.getTaxonNodeService().find((Integer)((RowId) taxonTree.getValue()).getId()[0]);
-			}
-			if(taxonNode==null){
-				taxonNode = (TaxonNode) classificationBox.getValue();
-			}
-			term = (TermVocabulary<NamedArea>) distAreaBox.getValue();
-			Set<NamedArea> selectedAreas = (Set<NamedArea>) namedAreaList.getValue();
-			DistributionEditorUtil.openDistributionView(taxonNode, term, selectedAreas);
-			window.close();
-		}
-		else if(source==cancelButton){
-			window.close();
-		}
-	}
+    @Override
+    public void valueChange(ValueChangeEvent event) {
+        Property property = event.getProperty();
+        if(property==classificationBox){
+            TaxonNode parentNode = (TaxonNode) event.getProperty().getValue();
+            if(parentNode!=null){
+                UUID uuid = parentNode.getUuid();
+                int id = parentNode.getId();
+                String titleCache = parentNode.getClassification().getTitleCache();
+                UuidAndTitleCache<TaxonNode> parent = new UuidAndTitleCache<>(uuid, id, titleCache);
+                taxonTree.setContainerDataSource(new TaxonNodeContainer(parent));
+            }
+            else{
+                taxonTree.setContainerDataSource(null);
+            }
+        }
+
+        else if(property==distAreaBox){
+            TermVocabulary<NamedArea> vocabulary = (TermVocabulary<NamedArea>) event.getProperty().getValue();
+            NamedAreaContainer container = new NamedAreaContainer(vocabulary);
+            namedAreaList.setContainerDataSource(container);
+        }
+        updateButtons();
+    }
+
+    @Override
+    protected boolean isValid() {
+        return classificationBox.getValue()!=null && distAreaBox.getValue()!=null;
+    }
+
+    @Override
+    public void buttonClick(ClickEvent event) {
+        Object source = event.getSource();
+        if(source==okButton){
+            TaxonNode taxonNode = null;
+            TermVocabulary<NamedArea> term = null;
+            //TODO use field converter
+            if(taxonTree.getValue()!=null){
+                taxonNode = CdmSpringContextHelper.getTaxonNodeService().find((Integer)((RowId) taxonTree.getValue()).getId()[0]);
+            }
+            if(taxonNode==null){
+                taxonNode = (TaxonNode) classificationBox.getValue();
+            }
+            term = (TermVocabulary<NamedArea>) distAreaBox.getValue();
+            Set<NamedArea> selectedAreas = (Set<NamedArea>) namedAreaList.getValue();
+            DistributionEditorUtil.openDistributionView(taxonNode, term, selectedAreas);
+            window.close();
+        }
+        else if(source==cancelButton){
+            window.close();
+        }
+    }
+
+    @Override
+    public void nodeExpand(ExpandEvent event) {
+        UuidAndTitleCache<TaxonNode> parent = (UuidAndTitleCache<TaxonNode>) event.getItemId();
+        Collection<UuidAndTitleCache<TaxonNode>> children = CdmSpringContextHelper.getTaxonNodeService().listChildNodesAsUuidAndTitleCache(parent);
+        taxonTree.setChildrenAllowed(parent, !children.isEmpty());
+        for (UuidAndTitleCache<TaxonNode> child : children) {
+            Item childItem = taxonTree.addItem(child);
+            if(childItem!=null){
+                taxonTree.setParent(child, parent);
+                childItem.getItemProperty(TaxonNodeContainer.LABEL).setValue(child.getTitleCache());
+            }
+            Collection<UuidAndTitleCache<TaxonNode>> grandChildren = CdmSpringContextHelper.getTaxonNodeService().listChildNodesAsUuidAndTitleCache(child);
+            taxonTree.setChildrenAllowed(child, !grandChildren.isEmpty());
+        }
+    }
 
 }
