1 | /* |
---|
2 | * Copyright (C) 2014 CLARIN |
---|
3 | * |
---|
4 | * This program is free software: you can redistribute it and/or modify |
---|
5 | * it under the terms of the GNU General Public License as published by |
---|
6 | * the Free Software Foundation, either version 3 of the License, or |
---|
7 | * (at your option) any later version. |
---|
8 | * |
---|
9 | * This program is distributed in the hope that it will be useful, |
---|
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
12 | * GNU General Public License for more details. |
---|
13 | * |
---|
14 | * You should have received a copy of the GNU General Public License |
---|
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
---|
16 | */ |
---|
17 | package eu.clarin.cmdi.vlo.wicket.provider; |
---|
18 | |
---|
19 | import com.google.common.base.Predicate; |
---|
20 | import com.google.common.collect.ImmutableList; |
---|
21 | import com.google.common.collect.Iterables; |
---|
22 | import com.google.common.collect.Ordering; |
---|
23 | import eu.clarin.cmdi.vlo.pojo.FieldValuesOrder; |
---|
24 | import java.util.Iterator; |
---|
25 | import java.util.List; |
---|
26 | import org.apache.solr.client.solrj.response.FacetField; |
---|
27 | import org.apache.solr.client.solrj.response.FacetField.Count; |
---|
28 | import org.apache.wicket.extensions.markup.html.repeater.util.SortParam; |
---|
29 | import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider; |
---|
30 | import org.apache.wicket.model.IModel; |
---|
31 | import org.apache.wicket.model.Model; |
---|
32 | |
---|
33 | /** |
---|
34 | * Provides facet values and counts (both through the {@link Count} object of |
---|
35 | * SOLR) present on a {@link FacetField}, sortable by either count or name |
---|
36 | * |
---|
37 | * @see FieldValuesOrder |
---|
38 | * @author twagoo |
---|
39 | */ |
---|
40 | public class FacetFieldValuesProvider extends SortableDataProvider<FacetField.Count, FieldValuesOrder> { |
---|
41 | |
---|
42 | private final IModel<FacetField> model; |
---|
43 | private final int maxNumberOfItems; |
---|
44 | |
---|
45 | /** |
---|
46 | * Creates a provider without a maximum number of values. Bound to |
---|
47 | * {@link Integer#MAX_VALUE}. |
---|
48 | * |
---|
49 | * @param model FacetField model to get values and counts for |
---|
50 | */ |
---|
51 | public FacetFieldValuesProvider(IModel<FacetField> model) { |
---|
52 | this(model, Integer.MAX_VALUE); |
---|
53 | } |
---|
54 | |
---|
55 | public FacetFieldValuesProvider(IModel<FacetField> model, int max) { |
---|
56 | this(model, max, new SortParam<FieldValuesOrder>(FieldValuesOrder.COUNT, false)); |
---|
57 | } |
---|
58 | |
---|
59 | /** |
---|
60 | * Creates a provider with a set maximum number of values |
---|
61 | * |
---|
62 | * @param model FacetField model to get values and counts for |
---|
63 | * @param max maximum number of values to show |
---|
64 | * @param sort initial sort property and order |
---|
65 | */ |
---|
66 | public FacetFieldValuesProvider(IModel<FacetField> model, int max, SortParam<FieldValuesOrder> sort) { |
---|
67 | this.model = model; |
---|
68 | this.maxNumberOfItems = max; |
---|
69 | setSort(sort); |
---|
70 | } |
---|
71 | |
---|
72 | /** |
---|
73 | * override to achieve filtering |
---|
74 | * |
---|
75 | * @return model of string items should begin with |
---|
76 | */ |
---|
77 | protected IModel<String> getFilterModel() { |
---|
78 | return null; |
---|
79 | } |
---|
80 | |
---|
81 | @Override |
---|
82 | public Iterator<? extends FacetField.Count> iterator(long first, long count) { |
---|
83 | // get all the values |
---|
84 | final List<FacetField.Count> values = model.getObject().getValues(); |
---|
85 | // filter results |
---|
86 | final Iterable<Count> filtered = filter(values); |
---|
87 | // sort what remains |
---|
88 | final ImmutableList sorted = getOrdering().immutableSortedCopy(filtered); |
---|
89 | // return iterator starting at specified offset |
---|
90 | return sorted.listIterator((int) first); |
---|
91 | } |
---|
92 | |
---|
93 | @Override |
---|
94 | public long size() { |
---|
95 | if (hasFilter()) { |
---|
96 | final List<FacetField.Count> values = model.getObject().getValues(); |
---|
97 | return Iterables.size(filter(values)); |
---|
98 | } else { |
---|
99 | // Use value count from Solr, faster. |
---|
100 | // |
---|
101 | // Actual value count might be higher than what we want to show |
---|
102 | // so get minimum. |
---|
103 | return Math.min(maxNumberOfItems, model.getObject().getValueCount()); |
---|
104 | } |
---|
105 | } |
---|
106 | |
---|
107 | @Override |
---|
108 | public IModel<FacetField.Count> model(FacetField.Count object) { |
---|
109 | return new Model(object); |
---|
110 | } |
---|
111 | |
---|
112 | @Override |
---|
113 | public void detach() { |
---|
114 | model.detach(); |
---|
115 | } |
---|
116 | |
---|
117 | private Iterable<FacetField.Count> filter(List<FacetField.Count> list) { |
---|
118 | if (hasFilter()) { |
---|
119 | final String filterValue = getFilterModel().getObject().toLowerCase(); |
---|
120 | return Iterables.filter(list, new Predicate<FacetField.Count>() { |
---|
121 | @Override |
---|
122 | public boolean apply(Count input) { |
---|
123 | return input.getName().toLowerCase().startsWith(filterValue); |
---|
124 | } |
---|
125 | }); |
---|
126 | } else { |
---|
127 | return list; |
---|
128 | } |
---|
129 | } |
---|
130 | |
---|
131 | private boolean hasFilter() { |
---|
132 | return !(getFilterModel() == null || getFilterModel().getObject() == null || getFilterModel().getObject().isEmpty()); |
---|
133 | } |
---|
134 | |
---|
135 | private Ordering getOrdering() { |
---|
136 | final Ordering ordering; |
---|
137 | if (getSort().getProperty() == FieldValuesOrder.COUNT) { |
---|
138 | ordering = COUNT_ORDERING; |
---|
139 | } else if (getSort().getProperty() == FieldValuesOrder.NAME) { |
---|
140 | ordering = NAME_ORDERING; |
---|
141 | } else { |
---|
142 | ordering = Ordering.natural(); |
---|
143 | } |
---|
144 | |
---|
145 | if (getSort().isAscending()) { |
---|
146 | return ordering; |
---|
147 | } else { |
---|
148 | return ordering.reverse(); |
---|
149 | } |
---|
150 | } |
---|
151 | |
---|
152 | private static Ordering<FacetField.Count> COUNT_ORDERING = new Ordering<FacetField.Count>() { |
---|
153 | |
---|
154 | @Override |
---|
155 | public int compare(Count arg0, Count arg1) { |
---|
156 | // TODO: From old VLO: |
---|
157 | // IGNORABLE_VALUES (like "unknown") are move to the back of the list and should only be shown when you click "more...", unless the list is too small then whe can just show them. |
---|
158 | return Long.compare(arg0.getCount(), arg1.getCount()); |
---|
159 | } |
---|
160 | }; |
---|
161 | |
---|
162 | private static Ordering<FacetField.Count> NAME_ORDERING = new Ordering<FacetField.Count>() { |
---|
163 | |
---|
164 | @Override |
---|
165 | public int compare(Count arg0, Count arg1) { |
---|
166 | // TODO: From old VLO: |
---|
167 | // IGNORABLE_VALUES (like "unknown") are move to the back of the list and should only be shown when you click "more...", unless the list is too small then whe can just show them. |
---|
168 | return arg0.getName().compareTo(arg1.getName()); |
---|
169 | } |
---|
170 | }; |
---|
171 | |
---|
172 | } |
---|