source: vlo/branches/to-wicket-1.6/vlo_web_app/src/main/java/eu/clarin/cmdi/vlo/pages/FacetedSearchPage.java @ 4220

Last change on this file since 4220 was 4220, checked in by twagoo, 10 years ago

Merged twagoo branch of to-wicket-1.6 back to original, removed this branch

File size: 14.1 KB
Line 
1package eu.clarin.cmdi.vlo.pages;
2
3import eu.clarin.cmdi.vlo.FacetConstants;
4import eu.clarin.cmdi.vlo.Resources;
5import eu.clarin.cmdi.vlo.VloPageParameters;
6import eu.clarin.cmdi.vlo.config.VloConfig;
7import eu.clarin.cmdi.vlo.dao.AutoCompleteDao;
8import eu.clarin.cmdi.vlo.importer.FacetConceptMapping.FacetConcept;
9import eu.clarin.cmdi.vlo.importer.VLOMarshaller;
10import fiftyfive.wicket.basic.TruncatedLabel;
11import java.io.UnsupportedEncodingException;
12import java.net.URLEncoder;
13import java.util.ArrayList;
14import java.util.HashMap;
15import java.util.Iterator;
16import java.util.List;
17import java.util.Map;
18
19import org.apache.solr.client.solrj.SolrServerException;
20import org.apache.solr.client.solrj.response.FacetField;
21import org.apache.solr.common.SolrDocument;
22import org.apache.wicket.request.mapper.parameter.PageParameters;
23import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteTextField;
24import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackDefaultDataTable;
25import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
26import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
27import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
28import org.apache.wicket.extensions.markup.html.repeater.data.table.ISortableDataProvider;
29import org.apache.wicket.markup.html.WebMarkupContainer;
30import org.apache.wicket.markup.html.basic.Label;
31import org.apache.wicket.markup.html.basic.MultiLineLabel;
32import org.apache.wicket.markup.html.form.Button;
33import org.apache.wicket.markup.html.form.Form;
34import org.apache.wicket.markup.html.link.BookmarkablePageLink;
35import org.apache.wicket.markup.html.link.ExternalLink;
36import org.apache.wicket.markup.repeater.Item;
37import org.apache.wicket.markup.repeater.data.GridView;
38import org.apache.wicket.markup.repeater.data.IDataProvider;
39import org.apache.wicket.model.CompoundPropertyModel;
40import org.apache.wicket.model.IModel;
41import org.apache.wicket.model.ResourceModel;
42import org.apache.wicket.request.Url;
43import org.apache.wicket.request.cycle.RequestCycle;
44
45public class FacetedSearchPage extends BasePage {
46
47    private static final long serialVersionUID = 1L;
48
49    private final SearchPageQuery query;
50    private final static AutoCompleteDao autoCompleteDao = new AutoCompleteDao();
51    private final static String facetConceptsFile = VloConfig.getFacetConceptsFile();
52    private final static Map<String, FacetConcept> facetNameMap = VLOMarshaller.getFacetConceptMapping(facetConceptsFile).getFacetConceptMap();
53
54    public FacetedSearchPage(PageParameters params) {
55        this(VloPageParameters.convert(params));
56    }
57
58    /**
59     * @param parameters Page parameters
60     * @throws SolrServerException
61     */
62    public FacetedSearchPage(final VloPageParameters parameters) {
63        super(parameters);
64        query = new SearchPageQuery(parameters);
65        addSearchBox();
66        addFacetColumns();
67        addSearchResults();
68        addSearchServiceForm();
69    }
70
71    @SuppressWarnings("serial")
72    private class SearchBoxForm extends Form<SearchPageQuery> {
73
74        private final AutoCompleteTextField<String> searchBox;
75
76        /*
77         * Add multiline list of selected facet values
78         */
79        private void addFacetOverview() {
80
81            // get a map of the facets currently selected
82            Map<String, String> selectedFacets;
83            selectedFacets = query.getFilterQueryMap();
84
85            // create an interator for walking over the facets
86            Iterator<Map.Entry<String, String>> entries
87                    = selectedFacets.entrySet().iterator();
88
89            /*
90             * Wicket label to be used to show the list of facets that have been
91             * selected.
92             */
93            MultiLineLabel facetOverview;
94
95            // walk over the facets
96            if (!entries.hasNext()) {
97                // not a single facet has been selected
98                facetOverview = new MultiLineLabel("facetOverview",
99                        "No facets values selected");
100            } else {
101                // at least one facet has been selected
102
103                String string = "Selected facet values:  ";
104
105                // start building the the multiline label here
106                String[] facetFields;
107                int i = 0, lineLength = 0,
108                        maxLineLength = VloConfig.getFacetOverviewLength();
109                Boolean hasPrevious = false;
110
111                /*
112                 * Get the facet fields. We need them in order to display
113                 * the values in the overview in the same order as their
114                 * respective facets are listed in the boxes. Store multiple
115                 * lines in one string.
116                 */
117                facetFields = VloConfig.getFacetFields();
118
119                while (i < facetFields.length) {
120
121                    // check if facet field is in selected facets map
122                    if (selectedFacets.containsKey(facetFields[i])) {
123                        String value = selectedFacets.get(facetFields[i]);
124                        lineLength = lineLength + value.length();
125
126                        if (hasPrevious) {
127                            string = string.concat(", ");
128                        }
129
130                        if (lineLength > maxLineLength) {
131                            string = string.concat("\n");
132                            lineLength = 0;
133                            hasPrevious = false;
134                        }
135
136                        string = string.concat(value);
137                        hasPrevious = true;
138                    }
139                    i++;
140                }
141
142                // create a new wicket multi line label
143                facetOverview = new MultiLineLabel("facetOverview", string);
144            }
145
146            // finally, merge the label to the form
147            this.add(facetOverview);
148        }
149
150        public SearchBoxForm(String id, SearchPageQuery query) {
151            super(id, new CompoundPropertyModel<SearchPageQuery>(query));
152            add(new ExternalLink("vloHomeLink", VloConfig.getHomeUrl()));
153
154            searchBox = new AutoCompleteTextField<String>("searchQuery") {
155                @Override
156                protected Iterator<String> getChoices(String input) {
157                    return autoCompleteDao.getChoices(input).iterator();
158                }
159            };
160
161            add(searchBox);
162            Button submit = new Button("searchSubmit");
163            add(submit);
164
165            // merge link to help menu page
166            String helpUrl = VloConfig.getHelpUrl();
167            ExternalLink helpLink = new ExternalLink("helpLink", helpUrl, "help");
168            add(helpLink);
169
170            VloPageParameters param;
171            param = new VloPageParameters(query.getPageParameters());
172
173            final RequestCycle reqCycle = getRequestCycle();
174            final Url reqUrl = Url.parse(reqCycle.urlFor(ShowResultPage.class, param.convert()));
175            String thisURL = reqCycle.getUrlRenderer().renderFullUrl(reqUrl);
176
177            try {
178                thisURL = URLEncoder.encode(thisURL, "UTF-8");
179            } catch (UnsupportedEncodingException e) {
180            }
181
182            String feedbackFormUrl = VloConfig.getFeedbackFromUrl() + thisURL;
183            ExternalLink feedbackLink = new ExternalLink("feedbackLink", feedbackFormUrl, "found an error?");
184            add(feedbackLink);
185
186            addFacetOverview();
187        }
188
189        @Override
190        protected void onSubmit() {
191            SearchPageQuery query = getModelObject();
192            PageParameters param = query.getPageParameters();
193
194            VloPageParameters newParam = new VloPageParameters();
195
196            setResponsePage(FacetedSearchPage.class, newParam);
197        }
198    }
199
200    private void addSearchBox() {
201        add(new SearchBoxForm("searchForm", query));
202    }
203
204    @SuppressWarnings("serial")
205    private void addFacetColumns() {
206        GridView<FacetField> facetColumns = new GridView<FacetField>("facetColumns", (IDataProvider<FacetField>) new SolrFacetDataProvider(query.getSolrQuery()
207                .getCopy())) {
208                    @Override
209                    protected void populateItem(Item<FacetField> item) {
210                        String facetName = ((FacetField) item.getDefaultModelObject()).getName();
211                        String descriptionTooltip = "";
212                        if (facetNameMap.containsKey(facetName)) {
213                            descriptionTooltip = facetNameMap.get(facetName).getDescription();
214                        }
215                        item.add(new FacetBoxPanel("facetBox", item.getModel(), descriptionTooltip).create(query));
216                    }
217
218                    @Override
219                    protected void populateEmptyItem(Item<FacetField> item) {
220                        item.add(new Label("facetBox", ""));
221                    }
222                };
223        facetColumns.setColumns(2);
224        add(facetColumns);
225    }
226
227    @SuppressWarnings("serial")
228    private void addSearchResults() {
229        List<IColumn<SolrDocument, String>> columns;
230        columns = new ArrayList<IColumn<SolrDocument, String>>();
231        columns.add(new AbstractColumn<SolrDocument, String>(new ResourceModel(Resources.NAME)) {
232
233            @Override
234            public void populateItem(Item<ICellPopulator<SolrDocument>> cellItem, String componentId, IModel<SolrDocument> rowModel) {
235                cellItem.add(new DocumentLinkPanel(componentId, rowModel, query));
236            }
237        });
238        columns.add(new AbstractColumn<SolrDocument, String>(new ResourceModel(Resources.DESCRIPTION)) {
239
240            @Override
241            public void populateItem(Item<ICellPopulator<SolrDocument>> cellItem, String componentId, IModel<SolrDocument> rowModel) {
242                String descriptionText = (String) rowModel.getObject().getFirstValue(FacetConstants.FIELD_DESCRIPTION);
243                cellItem.add(new TruncatedLabel(componentId, 100, descriptionText));
244            }
245        });
246        AjaxFallbackDefaultDataTable<SolrDocument, String> searchResultList = new AjaxFallbackDefaultDataTable<SolrDocument, String>("searchResults", columns, (ISortableDataProvider<SolrDocument, String>) new SolrDocumentDataProvider(query.getSolrQuery().getCopy()), 30);
247
248        add(searchResultList);
249    }
250
251    /**
252     * Add contentSearch form (FCS)
253     *
254     * @param solrDocument
255     */
256    private void addSearchServiceForm() {
257
258        BookmarkablePageLink link;
259        link = new BookmarkablePageLink("link", FacetedSearchPage.class);
260        link.add(new Label("naar deze pagina"));
261
262        // get values for cql endpoint substitution
263        String cqlEndpointFilter = VloConfig.getCqlEndpointFilter();
264        String cqlEndpointAlternative = VloConfig.getCqlEndpointAlternative();
265
266        final WebMarkupContainer contentSearchContainer = new WebMarkupContainer("contentSearch");
267        add(contentSearchContainer);
268
269        // get all documents with an entry for the FCS
270        SearchServiceDataProvider dataProvider = new SearchServiceDataProvider(query.getSolrQuery());
271        if (dataProvider.size() > 0 && dataProvider.size() <= 200) {    // at least one and not more than x records with FCS endpoint in result set?
272            try {
273                // building map (CQL endpoint -> List of resource IDs)
274                HashMap<String, List<String>> aggregationContextMap = new HashMap<String, List<String>>();
275
276                int offset = 0;
277                int fetchSize = 1000;
278                int totalResults = (int) dataProvider.size();
279                while (offset < totalResults) {
280                    Iterator<SolrDocument> iter = dataProvider.iterator(offset, fetchSize);
281                    while (iter.hasNext()) {
282                        SolrDocument document = iter.next();
283                        String id = document.getFirstValue(FacetConstants.FIELD_ID).toString();
284                        String fcsEndpoint = document.getFirstValue(FacetConstants.FIELD_SEARCH_SERVICE).toString();
285                        if (aggregationContextMap.containsKey(fcsEndpoint)) {
286                            aggregationContextMap.get(fcsEndpoint).add(id);
287                        } else {
288                            List<String> idArray = new ArrayList<String>();
289                            idArray.add(id);
290
291                            // substitute endpoint
292                            if (cqlEndpointFilter.length() == 0) {
293                                // no substitution
294                            } else {
295                                // check for the need to substitute
296                            }
297
298                            if (cqlEndpointFilter.equals(cqlEndpointFilter)) {
299                                // no substitution, take the value from the record
300                                aggregationContextMap.put(fcsEndpoint, idArray);
301                            } else {
302                                // substitution, take the alternative url
303                                aggregationContextMap.put(cqlEndpointAlternative, idArray);
304                            }
305                        }
306                    }
307
308                    offset += fetchSize;
309                }
310
311                // merge HTML form to container
312                String labelString;
313                if (totalResults == 1) {
314                    labelString = "Plain text search via Federated Content Search (supported by one resource in this result set)";
315                } else {
316                    labelString = "Plain text search via Federated Content Search (supported by " + totalResults
317                            + " resources in this result set)";
318                }
319                Label contentSearchLabel = new Label("contentSearchForm", HtmlFormCreator.getContentSearchForm(
320                        aggregationContextMap, labelString));
321                contentSearchLabel.setEscapeModelStrings(false);
322                contentSearchContainer.add(contentSearchLabel);
323                // contentSearchContainer.merge(link);
324            } catch (UnsupportedEncodingException uee) {
325                contentSearchContainer.setVisible(false);
326            }
327        } else {
328            contentSearchContainer.setVisible(false);
329        }
330    }
331}
Note: See TracBrowser for help on using the repository browser.