Project

General

Profile

Revision b8e7047b

IDb8e7047b969d45deea4db1b3b4e248de38377055
Parent a8118bab
Child d196eb4d

Added by Patrick Plitzner about 5 years ago

ref #5458 Performance increase for taxon node selection

  • by using SqlContainer the nodes are lazily loaded
  • child nodes are loaded via a second SQL query which is filtered for parent_id when expanding a node
  • parent-child relations are cached

View differences:

src/main/java/eu/etaxonomy/cdm/vaadin/container/TaxonNodeContainer.java
2 2

  
3 3
import java.util.ArrayList;
4 4
import java.util.Arrays;
5
import java.util.Collection;
5 6
import java.util.List;
6 7

  
7 8
import com.vaadin.data.Item;
......
18 19
	private static final long serialVersionUID = 102401340698963360L;
19 20
	public static final String LABEL = "label";
20 21

  
22
	private final List<String> nodeInitStrategy = Arrays.asList(new String[]{
23
	        "taxon.sec",
24
	        "taxon.name",
25
	        "classification"
26
	});
27

  
21 28
	/**
22 29
	 * Creates a new taxon node container
23 30
	 * @param parentNode the parent node which will <b>not</b> be included
......
25 32
	 */
26 33
	public TaxonNodeContainer(TaxonNode parentNode) {
27 34
		addContainerProperty(LABEL, String.class, "[no taxon]");
28
		getTaxonNodeList(parentNode);
35
		if(parentNode==null){
36
            //just load classifications
37
            IClassificationService classificationService = CdmSpringContextHelper.getClassificationService();
38
            List<Classification> classificationList = classificationService.listClassifications(null, null, null, nodeInitStrategy);
39
            for (Classification classification : classificationList) {
40
                TaxonNode rootNode = classification.getRootNode();
41
                Item item = addItem(rootNode);
42
                if(rootNode.getClassification()!=null){
43
                    item.getItemProperty(LABEL).setValue(rootNode.getClassification().getName().getText());
44
                }
45
            }
46
        }
47
		else{
48
		    addItem(parentNode);
49
		}
50
//		getTaxonNodeList(parentNode);
29 51
	}
30 52

  
53
	@Override
54
	public Collection<?> getChildren(Object itemId) {
55
	    List<TaxonNode> childNodes = ((TaxonNode) itemId).getChildNodes();
56
	    for (TaxonNode taxonNode : childNodes) {
57
            if(!containsId(taxonNode)){
58
                setParent(taxonNode, itemId);
59
            }
60
        }
61
        return childNodes;
62
	}
63

  
64
	/**
65
	 * {@inheritDoc}
66
	 */
67
	@Override
68
	public Object getParent(Object itemId) {
69
	    return ((TaxonNode) itemId).getParent();
70
	}
71

  
72
    /**
73
     * {@inheritDoc}
74
     */
75
    @Override
76
    public boolean hasChildren(Object itemId) {
77
        return !((TaxonNode)itemId).getChildNodes().isEmpty();
78
    }
79

  
31 80
	public void getTaxonNodeList(TaxonNode parentNode) {
32 81
		List<TaxonNode> nodes = new ArrayList<TaxonNode>();
33 82

  
34
		List<String> nodeInitStrategy = Arrays.asList(new String[]{
35
	            "taxon.sec",
36
	            "taxon.name",
37
	            "classification"
38
	    });
39 83

  
40 84
		if(parentNode==null){
41 85
			//just load classifications
src/main/java/eu/etaxonomy/cdm/vaadin/container/TaxonTreeContainer.java
1
// $Id$
2
/**
3
* Copyright (C) 2016 EDIT
4
* European Distributed Institute of Taxonomy
5
* http://www.e-taxonomy.eu
6
*
7
* The contents of this file are subject to the Mozilla Public License Version 1.1
8
* See LICENSE.TXT at the top of this package for the full license terms.
9
*/
10
package eu.etaxonomy.cdm.vaadin.container;
11

  
12
import java.sql.SQLException;
13
import java.util.ArrayList;
14
import java.util.Collection;
15
import java.util.HashMap;
16
import java.util.HashSet;
17
import java.util.List;
18
import java.util.Map;
19

  
20
import com.vaadin.data.Container.Hierarchical;
21
import com.vaadin.data.util.filter.Compare;
22
import com.vaadin.data.util.sqlcontainer.RowId;
23

  
24
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
25
import eu.etaxonomy.cdm.vaadin.util.CdmQueryFactory;
26

  
27
/**
28
 * @author pplitzner
29
 * @date 18.10.2016
30
 *
31
 */
32
public class TaxonTreeContainer extends CdmSQLContainer implements Hierarchical{
33

  
34
    private static final long serialVersionUID = 5488629563366944491L;
35

  
36
    private final Collection<RowId> rootItemIds = new HashSet<>();
37
    private final Map<Object, List<Object>> parentChildMap = new HashMap<>();
38
    private final Map<Object, Object> childParentMap = new HashMap<>();
39
    private CdmSQLContainer childrenContainer;
40

  
41
    public TaxonTreeContainer(TaxonNode parentNode) throws SQLException {
42
        super(CdmQueryFactory.generateTaxonTreeQuery("Name", Integer.toString(parentNode.getClassification().getId())));
43
        childrenContainer = new CdmSQLContainer(CdmQueryFactory.generateTaxonTreeQuery("Name", Integer.toString(parentNode.getClassification().getId())));
44
        List<TaxonNode> childNodes = parentNode.getChildNodes();
45
        for (TaxonNode taxonNode : childNodes) {
46
            rootItemIds.add(new RowId(taxonNode.getId()));
47
        }
48
    }
49

  
50
    /**
51
     * {@inheritDoc}
52
     */
53
    @Override
54
    public Collection<?> getChildren(Object itemId) {
55
        List<Object> children = parentChildMap.get(itemId);
56
        if(children==null){
57
            children = updateChildren(itemId);
58
        }
59
        return children;
60
    }
61

  
62
    private List<Object> updateChildren(Object itemId) {
63
        List<Object> children;
64
        Filter childrenOfTaxonFilter = new Compare.Equal("tn.parent_id", Integer.valueOf(itemId.toString()));
65
        childrenContainer.addContainerFilter(childrenOfTaxonFilter);
66
        children = new ArrayList<>();
67
        Collection<?> itemIds = childrenContainer.getItemIds();
68
        for (Object object : itemIds) {
69
            childParentMap.put(object, itemId);
70
            children.add(object);
71
        }
72
        childrenContainer.removeAllContainerFilters();
73

  
74
        parentChildMap.put(itemId, children);
75
        return children;
76
    }
77

  
78
    /**
79
     * {@inheritDoc}
80
     */
81
    @Override
82
    public Object getParent(Object itemId) {
83
        return childParentMap.get(itemId);
84
    }
85

  
86
    /**
87
     * {@inheritDoc}
88
     */
89
    @Override
90
    public boolean hasChildren(Object itemId) {
91
        List<Object> children = parentChildMap.get(itemId);
92
        if(children==null){
93
            children = updateChildren(itemId);
94
        }
95
        return !children.isEmpty();
96
    }
97

  
98
    /**
99
     * {@inheritDoc}
100
     */
101
    @Override
102
    public Collection<?> rootItemIds() {
103
        return rootItemIds;
104
    }
105

  
106
    /**
107
     * {@inheritDoc}
108
     */
109
    @Override
110
    public boolean setParent(Object itemId, Object newParentId) throws UnsupportedOperationException {
111
        return true;
112
    }
113

  
114
    /**
115
     * {@inheritDoc}
116
     */
117
    @Override
118
    public boolean areChildrenAllowed(Object itemId) {
119
        return hasChildren(itemId);
120
    }
121

  
122
    /**
123
     * {@inheritDoc}
124
     */
125
    @Override
126
    public boolean setChildrenAllowed(Object itemId, boolean areChildrenAllowed) throws UnsupportedOperationException {
127
        return true;
128
    }
129

  
130
    /**
131
     * {@inheritDoc}
132
     */
133
    @Override
134
    public boolean isRoot(Object itemId) {
135
        return itemId==null?true:rootItemIds.contains(itemId);
136
    }
137

  
138

  
139

  
140
}
src/main/java/eu/etaxonomy/cdm/vaadin/util/CdmQueryFactory.java
40 40
    public static final String ID = "id";
41 41
    public static final String UUID_ID = "uuid";
42 42

  
43
    public static QueryDelegate generateTaxonTreeQuery(String name_id, String classificationId) throws SQLException {
44
        String FROM_QUERY = " FROM TaxonBase tb " +
45
                "INNER JOIN TaxonNode tn on tn.taxon_id=tb.id " +
46
                "INNER JOIN TaxonNameBase tnb on tb.name_id=tnb.id " +
47
                "INNER JOIN Classification cl on cl.id=tn.classification_id and cl.id='"+classificationId+"'";
48
        String SELECT_QUERY="SELECT tn.id as " + ID +
49
                ", tb.uuid as " + UUID_ID +
50
                ", tnb.titleCache as " + name_id +
51
                ", tn.parent_id as parent" +
52
                FROM_QUERY;
53
        String COUNT_QUERY = "SELECT count(*) " + FROM_QUERY;
54
        String CONTAINS_QUERY = "SELECT * FROM TaxonBase tb WHERE tb.id = ?";
55

  
56
        return generateQueryDelegate(SELECT_QUERY, COUNT_QUERY, CONTAINS_QUERY);
57
    }
58

  
43 59
    public static QueryDelegate generateTaxonBaseQuery(String name_id,
44 60
            String pb_id,
45 61
            String unp_id,
src/main/java/eu/etaxonomy/cdm/vaadin/view/dbstatus/DistributionSettingsConfigWindow.java
9 9
*/
10 10
package eu.etaxonomy.cdm.vaadin.view.dbstatus;
11 11

  
12
import java.sql.SQLException;
12 13
import java.util.Set;
13 14

  
14 15
import com.vaadin.data.Container;
15 16
import com.vaadin.data.Property;
16 17
import com.vaadin.data.Property.ValueChangeEvent;
17 18
import com.vaadin.data.Property.ValueChangeListener;
19
import com.vaadin.data.util.sqlcontainer.RowId;
18 20
import com.vaadin.server.VaadinSession;
19 21
import com.vaadin.ui.AbstractLayout;
20 22
import com.vaadin.ui.Alignment;
......
27 29
import com.vaadin.ui.Label;
28 30
import com.vaadin.ui.ListSelect;
29 31
import com.vaadin.ui.Notification;
30
import com.vaadin.ui.Tree;
32
import com.vaadin.ui.Table.ColumnHeaderMode;
33
import com.vaadin.ui.TreeTable;
31 34
import com.vaadin.ui.VerticalLayout;
32 35
import com.vaadin.ui.Window;
33 36

  
......
36 39
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
37 40
import eu.etaxonomy.cdm.vaadin.container.NamedAreaContainer;
38 41
import eu.etaxonomy.cdm.vaadin.container.TaxonNodeContainer;
42
import eu.etaxonomy.cdm.vaadin.container.TaxonTreeContainer;
39 43
import eu.etaxonomy.cdm.vaadin.presenter.dbstatus.settings.SettingsPresenter;
44
import eu.etaxonomy.cdm.vaadin.util.CdmSpringContextHelper;
40 45
import eu.etaxonomy.cdm.vaadin.util.DistributionEditorUtil;
41 46

  
42 47
/**
......
50 55
	private ComboBox classificationBox;
51 56
    private ComboBox distAreaBox;
52 57
    private ListSelect namedAreaList;
53
    private Tree taxonTree;
54
    private Label labelNoClassification;
58
    private TreeTable taxonTree;
55 59
    private Button okButton;
56 60
    private Button cancelButton;
57 61
    private final SettingsPresenter presenter;
......
83 87
		classificationBox.addValueChangeListener(this);
84 88
        if(chosenTaxonNode!=null){
85 89
        	classificationBox.setValue(chosenTaxonNode.getClassification().getRootNode());
86
        	taxonTree.setContainerDataSource(new TaxonNodeContainer((TaxonNode) classificationBox.getValue()));
87
        	taxonTree.setValue(chosenTaxonNode);
90
        	try {
91
                taxonTree.setContainerDataSource(new TaxonTreeContainer((TaxonNode) classificationBox.getValue()));
92
            } catch (SQLException e) {
93
                // TODO Auto-generated catch block
94
                e.printStackTrace();
95
            }
96
        	taxonTree.select(new RowId(chosenTaxonNode.getId()));
97
            taxonTree.setVisibleColumns("Name");
88 98
        }
89
        taxonTree.setItemCaptionPropertyId(TaxonNodeContainer.LABEL);
90 99
        distAreaBox.setContainerDataSource(distributionContainer);
91 100
        distAreaBox.setValue(chosenArea);
92 101
        distAreaBox.addValueChangeListener(this);
......
123 132
        VerticalLayout leftContainer = new VerticalLayout();
124 133
        leftContainer.setImmediate(false);
125 134
        leftContainer.setSpacing(true);
135
        leftContainer.setSizeFull();
126 136

  
127 137
        VerticalLayout rightContainer = new VerticalLayout();
128 138
        rightContainer.setImmediate(false);
129 139
        rightContainer.setSpacing(true);
140
        rightContainer.setSizeFull();
130 141

  
131 142
        //classification and term
132 143
        classificationBox = new ComboBox("Classification");
......
142 153
        // named areas
143 154
        namedAreaList = new ListSelect();
144 155
        namedAreaList.setCaption("Areas");
145
        namedAreaList.setWidth("100%");
146 156
        namedAreaList.setSizeFull();
147 157
        namedAreaList.setMultiSelect(true);
148 158

  
149 159
        //taxonomy
150
        taxonTree = new Tree("Taxonomy");
151
        taxonTree.setImmediate(false);
152

  
153
        //no classification selected label
154
        labelNoClassification = new Label(" - Please select a classification - ");
160
        taxonTree = new TreeTable("Taxonomy");
161
        taxonTree.setSelectable(true);
162
        taxonTree.setSizeFull();
163
        taxonTree.setImmediate(true);
164
        taxonTree.setPageLength(20);
165
        taxonTree.setCacheRate(20);
166
        taxonTree.setColumnHeaderMode(ColumnHeaderMode.HIDDEN);
155 167

  
156 168
        leftContainer.addComponent(distAreaBox);
157 169
        leftContainer.setExpandRatio(distAreaBox, 0.1f);
......
162 174
        rightContainer.addComponent(classificationBox);
163 175
        rightContainer.setExpandRatio(classificationBox, 0.1f);
164 176
        rightContainer.addComponent(taxonTree);
165
        rightContainer.setExpandRatio(taxonTree, 1);
166
        rightContainer.addComponent(labelNoClassification);
167
        rightContainer.setComponentAlignment(labelNoClassification, Alignment.BOTTOM_RIGHT);
177
        rightContainer.setExpandRatio(taxonTree, 1f);
168 178

  
169 179
        mainLayout.addComponent(leftContainer);
170 180
        mainLayout.addComponent(rightContainer);
......
196 206
		if(property==classificationBox){
197 207
			TaxonNode parentNode = (TaxonNode) event.getProperty().getValue();
198 208
			if(parentNode!=null){
199
				taxonTree.setContainerDataSource(new TaxonNodeContainer(parentNode));
209
			    try {
210
                    taxonTree.setContainerDataSource(new TaxonTreeContainer(parentNode));
211
                    taxonTree.setVisibleColumns("Name");
212
                } catch (SQLException e) {
213
                    // TODO Auto-generated catch block
214
                    e.printStackTrace();
215
                }
200 216
			}
201 217
			else{
202 218
				taxonTree.setContainerDataSource(null);
203 219
			}
204
			labelNoClassification.setVisible(parentNode==null);
205 220
		}
206 221

  
207 222
		else if(property==distAreaBox){
......
217 232
		if(source==okButton){
218 233
			TaxonNode taxonNode;
219 234
			TermVocabulary<NamedArea> term = null;
220
			taxonNode = (TaxonNode) taxonTree.getValue();
235
			//TODO use field converter
236
			taxonNode = CdmSpringContextHelper.getTaxonNodeService().find((Integer)((RowId) taxonTree.getValue()).getId()[0]);
221 237
			if(taxonNode==null){
222 238
				taxonNode = (TaxonNode) classificationBox.getValue();
223 239
			}

Also available in: Unified diff

Add picture from clipboard (Maximum size: 40 MB)