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

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

After splitting of a branch (r4199) including code for moving from wicket 1.4 to wicket 6, some more modifications in the direction of that target.

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