cleanup
[cdm-vaadin.git] / src / main / java / eu / etaxonomy / cdm / service / TaxonNameStringFilterablePagingProvider.java
1 /**
2 * Copyright (C) 2017 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.cdm.service;
10
11 import java.util.ArrayList;
12 import java.util.Arrays;
13 import java.util.HashMap;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.UUID;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.vaadin.viritin.fields.LazyComboBox.FilterableCountProvider;
21
22 import com.vaadin.data.Property.ValueChangeListener;
23 import com.vaadin.ui.AbstractField;
24 import com.vaadin.ui.Field;
25
26 import eu.etaxonomy.cdm.api.service.INameService;
27 import eu.etaxonomy.cdm.api.service.pager.Pager;
28 import eu.etaxonomy.cdm.api.util.TaxonNamePartsFilter;
29 import eu.etaxonomy.cdm.model.name.Rank;
30 import eu.etaxonomy.cdm.model.name.TaxonName;
31 import eu.etaxonomy.cdm.persistence.dto.TaxonNameParts;
32 import eu.etaxonomy.cdm.persistence.query.MatchMode;
33 import eu.etaxonomy.cdm.persistence.query.OrderHint;
34
35 /**
36 * IMPORTANT !!!
37 *
38 * The string representations returned as rankSpecificNamePart must be unique in the database since these are being used as weak references between e.g.
39 * genus name and the TaxonName entity for this genus.
40 *
41 * @author a.kohlbecker
42 * @since Jun 7, 2017
43 *
44 */
45 public class TaxonNameStringFilterablePagingProvider implements FilterableStringRepresentationPagingProvider<UUID>, FilterableCountProvider {
46
47 private static final Logger logger = LogManager.getLogger();
48
49 private static final List<String> DEFAULT_INIT_STRATEGY = Arrays.asList("$");
50
51 private int pageSize = 20;
52
53 private INameService service;
54
55 private MatchMode matchMode = MatchMode.BEGINNING;
56
57 private List<OrderHint> orderHints = OrderHint.ORDER_BY_TITLE_CACHE.asList();
58
59 List<String> initStrategy = DEFAULT_INIT_STRATEGY;
60
61 private TaxonNamePartsFilter namePartsFilter = new TaxonNamePartsFilter();
62
63 private Map<AbstractField<String>, ValueChangeListener> registeredToFields = new HashMap<>();
64
65 private Map<String, UUID> lastPagedEntityUUIDs;
66
67
68 public TaxonNameStringFilterablePagingProvider(INameService service) {
69 this(service, Rank.GENUS(), null);
70 }
71
72 public TaxonNameStringFilterablePagingProvider(INameService service, Rank rank) {
73 this(service, rank, null);
74 }
75
76 public TaxonNameStringFilterablePagingProvider(INameService service, Rank rank, MatchMode matchMode) {
77 super();
78 this.service = service;
79 if(matchMode != null){
80 this.matchMode = matchMode;
81 }
82 namePartsFilter.setRank(rank);
83 }
84
85 public void listenToFields(AbstractField<String> genusOrUninomialField, AbstractField<String> infraGenericEpithetField,
86 AbstractField<String> specificEpithetField, AbstractField<String> infraSpecificEpithetField){
87
88 unlistenAllFields();
89
90 registerNullSave(genusOrUninomialField, e -> namePartsFilter.setGenusOrUninomial(genusOrUninomialField.getValue()));
91 registerNullSave(infraGenericEpithetField, e -> namePartsFilter.setGenusOrUninomial(infraGenericEpithetField.getValue()));
92 registerNullSave(specificEpithetField, e -> namePartsFilter.setGenusOrUninomial(specificEpithetField.getValue()));
93 registerNullSave(infraSpecificEpithetField, e -> namePartsFilter.setGenusOrUninomial(infraSpecificEpithetField.getValue()));
94 }
95
96 /**
97 *
98 */
99 public void unlistenAllFields() {
100 for(AbstractField<String> f : registeredToFields.keySet()){
101 f.removeValueChangeListener(registeredToFields.get(f));
102 }
103 registeredToFields.clear();
104 }
105
106 public void replaceFields(AbstractField<String> unlistenField, AbstractField<String> listenToField) throws UnknownFieldException{
107 if(registeredToFields.containsKey(unlistenField)){
108 ValueChangeListener listener = registeredToFields.get(unlistenField);
109 unlistenField.removeValueChangeListener(listener);
110 registeredToFields.remove(unlistenField);
111 registerNullSave(listenToField, listener);
112 } else {
113 throw new UnknownFieldException();
114 }
115 }
116
117 public void updateFromFields(){
118 for(AbstractField<String> f : registeredToFields.keySet()){
119 ValueChangeListener listener = registeredToFields.get(f);
120 listener.valueChange(new Field.ValueChangeEvent(f));
121 }
122 }
123
124 /**
125 * @param genusOrUninomialField
126 */
127 protected void registerNullSave(AbstractField<String> field, ValueChangeListener listener) {
128 if(field != null){
129 registeredToFields.put(field, listener);
130 field.addValueChangeListener(listener);
131 }
132 }
133
134 /**
135 * @return the matchMode
136 */
137 protected MatchMode getMatchMode() {
138 return matchMode;
139 }
140
141 /**
142 * @param matchMode the matchMode to set
143 */
144 protected void setMatchMode(MatchMode matchMode) {
145 this.matchMode = matchMode;
146 }
147
148 /**
149 * @return the orderHints
150 */
151 protected List<OrderHint> getOrderHints() {
152 return orderHints;
153 }
154
155 /**
156 * @param orderHints the orderHints to set
157 */
158 protected void setOrderHints(List<OrderHint> orderHints) {
159 this.orderHints = orderHints;
160 }
161
162 public TaxonNamePartsFilter getFilter(){
163 return namePartsFilter;
164 }
165
166 /**
167 * {@inheritDoc}
168 */
169 @Override
170 public List<String> findEntities(int firstRow, String filter) {
171
172 Integer pageIndex = firstRow / pageSize;
173 Pager<TaxonNameParts> taxonNamePager = service.findTaxonNameParts(namePartsFilter, filter, pageSize, pageIndex, orderHints);
174 if(logger.isTraceEnabled()){
175 logger.trace("findEntities() - page: " + taxonNamePager.getCurrentIndex() + "/" + taxonNamePager.getPagesAvailable() + " totalRecords: " + taxonNamePager.getCount() + "\n" + taxonNamePager.getRecords());
176 }
177 List<String> namePartStrings = new ArrayList<>(taxonNamePager.getRecords().size());
178 lastPagedEntityUUIDs = new HashMap<>(taxonNamePager.getRecords().size());
179 for(TaxonNameParts tnp : taxonNamePager.getRecords()){
180 String rankSpecificNamePart = tnp.rankSpecificNamePart();
181 String namePartKey = rankSpecificNamePart;
182 if(lastPagedEntityUUIDs.containsKey(namePartKey)){
183 namePartKey = rankSpecificNamePart + " DUPLICATE[" + tnp.getTaxonNameUuid() + "]";
184 }
185 namePartStrings.add(namePartKey);
186 lastPagedEntityUUIDs.put(namePartKey, tnp.getTaxonNameUuid());
187 }
188 return namePartStrings;
189 }
190
191 /**
192 * {@inheritDoc}
193 */
194 @Override
195 public int size(String filter) {
196
197 Pager<TaxonNameParts> taxonNamePager = service.findTaxonNameParts(namePartsFilter, filter, 1, 0, null);
198 if(logger.isTraceEnabled()){
199 logger.trace("size() - count: " + taxonNamePager.getCount().intValue());
200 }
201 return taxonNamePager.getCount().intValue();
202 }
203
204 /**
205 * @return the pageSize
206 */
207 public int getPageSize() {
208 return pageSize;
209 }
210
211 /**
212 * @param pageSize the pageSize to set
213 */
214 public void setPageSize(int pageSize) {
215 this.pageSize = pageSize;
216 }
217
218 /**
219 * @return the lastPagedEntityUUIDs
220 */
221 public Map<String, UUID> getLastPagedEntityUUIDs() {
222 return lastPagedEntityUUIDs;
223 }
224
225
226 public class UnknownFieldException extends Exception {
227
228 private static final long serialVersionUID = 1L;
229 }
230
231 /**
232 * {@inheritDoc}
233 */
234 @Override
235 public UUID idFor(String stringRepresentation) {
236 if(stringRepresentation == null){
237 return null;
238 }
239 if(lastPagedEntityUUIDs == null || !lastPagedEntityUUIDs.containsKey(stringRepresentation)){
240 int pages = Math.max(1, size(stringRepresentation));
241 for(int i = 0; i < pages; i++){
242 findEntities(i, stringRepresentation);
243 }
244 }
245 return lastPagedEntityUUIDs.get(stringRepresentation);
246 }
247
248 /**
249 * {@inheritDoc}
250 */
251 @Override
252 public void clearIdCache() {
253 lastPagedEntityUUIDs = null;
254 }
255
256 /**
257 * @param asList
258 * @return
259 */
260 public void excludeNames(TaxonName ... excludedTaxonNames) {
261 namePartsFilter.getExludedNamesUuids();
262 for(TaxonName n : excludedTaxonNames){
263 namePartsFilter.getExludedNamesUuids().add(n.getUuid());
264 }
265 }
266 }