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

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

Fixed parameterized links to faceted search page

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