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

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

Replaced calls getting session (either on component or statically) and casting to VloSession? with new convenience method VloSession?.get()

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