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

Last change on this file since 4232 was 4232, checked in by keeloo, 10 years ago

Removed VloPageParameters? class. ResourceLinkPanel? test is failing.

File size: 14.3 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
193            PageParameters newParam = new PageParameters();
194            // add the session persistent parameters
195            newParam.mergeWith(((VloSession)this.getSession()).getVloSessionPageParameters());
196
197            setResponsePage(FacetedSearchPage.class, newParam);
198        }
199    }
200
201    private void addSearchBox() {
202        add(new SearchBoxForm("searchForm", query));
203    }
204
205    @SuppressWarnings("serial")
206    private void addFacetColumns() {
207        GridView<FacetField> facetColumns = new GridView<FacetField>("facetColumns", (IDataProvider<FacetField>) new SolrFacetDataProvider(query.getSolrQuery()
208                .getCopy())) {
209                    @Override
210                    protected void populateItem(Item<FacetField> item) {
211                        String facetName = ((FacetField) item.getDefaultModelObject()).getName();
212                        String descriptionTooltip = "";
213                        if (facetNameMap.containsKey(facetName)) {
214                            descriptionTooltip = facetNameMap.get(facetName).getDescription();
215                        }
216                        item.add(new FacetBoxPanel("facetBox", item.getModel(), descriptionTooltip).create(query));
217                    }
218
219                    @Override
220                    protected void populateEmptyItem(Item<FacetField> item) {
221                        item.add(new Label("facetBox", ""));
222                    }
223                };
224        facetColumns.setColumns(2);
225        add(facetColumns);
226    }
227
228    @SuppressWarnings("serial")
229    private void addSearchResults() {
230        List<IColumn<SolrDocument, String>> columns;
231        columns = new ArrayList<IColumn<SolrDocument, String>>();
232        columns.add(new AbstractColumn<SolrDocument, String>(new ResourceModel(Resources.NAME)) {
233
234            @Override
235            public void populateItem(Item<ICellPopulator<SolrDocument>> cellItem, String componentId, IModel<SolrDocument> rowModel) {
236                cellItem.add(new DocumentLinkPanel(componentId, rowModel, query));
237            }
238        });
239        columns.add(new AbstractColumn<SolrDocument, String>(new ResourceModel(Resources.DESCRIPTION)) {
240
241            @Override
242            public void populateItem(Item<ICellPopulator<SolrDocument>> cellItem, String componentId, IModel<SolrDocument> rowModel) {
243                String descriptionText = (String) rowModel.getObject().getFirstValue(FacetConstants.FIELD_DESCRIPTION);
244                cellItem.add(new TruncatedLabel(componentId, 100, descriptionText));
245            }
246        });
247        AjaxFallbackDefaultDataTable<SolrDocument, String> searchResultList = new AjaxFallbackDefaultDataTable<SolrDocument, String>("searchResults", columns, (ISortableDataProvider<SolrDocument, String>) new SolrDocumentDataProvider(query.getSolrQuery().getCopy()), 30);
248
249        add(searchResultList);
250    }
251
252    /**
253     * Add contentSearch form (FCS)
254     *
255     * @param solrDocument
256     */
257    private void addSearchServiceForm() {
258
259        BookmarkablePageLink link;
260        link = new BookmarkablePageLink("link", FacetedSearchPage.class);
261        link.add(new Label("naar deze pagina"));
262
263        // get values for cql endpoint substitution
264        String cqlEndpointFilter = VloConfig.getCqlEndpointFilter();
265        String cqlEndpointAlternative = VloConfig.getCqlEndpointAlternative();
266
267        final WebMarkupContainer contentSearchContainer = new WebMarkupContainer("contentSearch");
268        add(contentSearchContainer);
269
270        // get all documents with an entry for the FCS
271        SearchServiceDataProvider dataProvider = new SearchServiceDataProvider(query.getSolrQuery());
272        if (dataProvider.size() > 0 && dataProvider.size() <= 200) {    // at least one and not more than x records with FCS endpoint in result set?
273            try {
274                // building map (CQL endpoint -> List of resource IDs)
275                HashMap<String, List<String>> aggregationContextMap = new HashMap<String, List<String>>();
276
277                int offset = 0;
278                int fetchSize = 1000;
279                int totalResults = (int) dataProvider.size();
280                while (offset < totalResults) {
281                    Iterator<SolrDocument> iter = dataProvider.iterator(offset, fetchSize);
282                    while (iter.hasNext()) {
283                        SolrDocument document = iter.next();
284                        String id = document.getFirstValue(FacetConstants.FIELD_ID).toString();
285                        String fcsEndpoint = document.getFirstValue(FacetConstants.FIELD_SEARCH_SERVICE).toString();
286                        if (aggregationContextMap.containsKey(fcsEndpoint)) {
287                            aggregationContextMap.get(fcsEndpoint).add(id);
288                        } else {
289                            List<String> idArray = new ArrayList<String>();
290                            idArray.add(id);
291
292                            // substitute endpoint
293                            if (cqlEndpointFilter.length() == 0) {
294                                // no substitution
295                            } else {
296                                // check for the need to substitute
297                            }
298
299                            if (cqlEndpointFilter.equals(cqlEndpointFilter)) {
300                                // no substitution, take the value from the record
301                                aggregationContextMap.put(fcsEndpoint, idArray);
302                            } else {
303                                // substitution, take the alternative url
304                                aggregationContextMap.put(cqlEndpointAlternative, idArray);
305                            }
306                        }
307                    }
308
309                    offset += fetchSize;
310                }
311
312                // add HTML form to container
313                String labelString;
314                if (totalResults == 1) {
315                    labelString = "Plain text search via Federated Content Search (supported by one resource in this result set)";
316                } else {
317                    labelString = "Plain text search via Federated Content Search (supported by " + totalResults
318                            + " resources in this result set)";
319                }
320                Label contentSearchLabel = new Label("contentSearchForm", HtmlFormCreator.getContentSearchForm(
321                        aggregationContextMap, labelString));
322                contentSearchLabel.setEscapeModelStrings(false);
323                contentSearchContainer.add(contentSearchLabel);
324                // contentSearchContainer.add(link);
325            } catch (UnsupportedEncodingException uee) {
326                contentSearchContainer.setVisible(false);
327            }
328        } else {
329            contentSearchContainer.setVisible(false);
330        }
331    }
332}
Note: See TracBrowser for help on using the repository browser.