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

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

Merging with session parameters in search form

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)this.getSession()).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)this.getSession()).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.