source: vlo/trunk/vlo-web-app/src/main/java/eu/clarin/cmdi/vlo/wicket/panels/BreadCrumbPanel.java @ 6012

Last change on this file since 6012 was 6012, checked in by Twan Goosen, 9 years ago

Converted field value shown in breadcrumbs panel
Refs #553

File size: 9.9 KB
Line 
1/*
2 * Copyright (C) 2014 CLARIN
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17package eu.clarin.cmdi.vlo.wicket.panels;
18
19import eu.clarin.cmdi.vlo.FacetConstants;
20import eu.clarin.cmdi.vlo.pojo.FacetSelection;
21import eu.clarin.cmdi.vlo.pojo.QueryFacetsSelection;
22import eu.clarin.cmdi.vlo.service.PageParametersConverter;
23import eu.clarin.cmdi.vlo.wicket.model.SolrFieldNameModel;
24import eu.clarin.cmdi.vlo.wicket.pages.FacetedSearchPage;
25import eu.clarin.cmdi.vlo.wicket.provider.FacetSelectionProvider;
26import eu.clarin.cmdi.vlo.wicket.provider.FieldValueConverterProvider;
27import java.util.Collection;
28import java.util.Iterator;
29import java.util.Locale;
30import java.util.Map;
31import org.apache.wicket.AttributeModifier;
32import org.apache.wicket.ajax.AjaxRequestTarget;
33import org.apache.wicket.ajax.markup.html.AjaxFallbackLink;
34import org.apache.wicket.markup.html.WebMarkupContainer;
35import org.apache.wicket.markup.html.basic.Label;
36import org.apache.wicket.markup.html.link.BookmarkablePageLink;
37import org.apache.wicket.markup.html.link.Link;
38import org.apache.wicket.markup.html.panel.GenericPanel;
39import org.apache.wicket.markup.repeater.Item;
40import org.apache.wicket.markup.repeater.data.DataView;
41import org.apache.wicket.model.IModel;
42import org.apache.wicket.model.PropertyModel;
43import org.apache.wicket.spring.injection.annot.SpringBean;
44import org.apache.wicket.util.convert.ConversionException;
45import org.apache.wicket.util.convert.IConverter;
46
47/**
48 * A panel representing the action trail that has lead to the current page in
49 * its current state with links to revert to a previous state (not completely
50 * linear given the nature of faceted browsing)
51 *
52 * @author twagoo
53 */
54public class BreadCrumbPanel extends GenericPanel<QueryFacetsSelection> {
55   
56    @SpringBean(name = "queryParametersConverter")
57    private PageParametersConverter<QueryFacetsSelection> paramsConverter;
58    @SpringBean
59    private FieldValueConverterProvider fieldValueConverterProvider;
60   
61    private final WebMarkupContainer query;
62    private final WebMarkupContainer facets;
63   
64    public BreadCrumbPanel(String id, IModel<QueryFacetsSelection> model) {
65        super(id, model);
66        add(new BookmarkablePageLink("searchPage", FacetedSearchPage.class));
67        add(query = createQuery(model, "query"));
68        add(facets = createFacets(model, "facets"));
69    }
70   
71    private WebMarkupContainer createQuery(final IModel<QueryFacetsSelection> selectionModel, String id) {
72        final WebMarkupContainer queryContainer = new WebMarkupContainer(id);
73        final Link link = new AjaxFallbackLink("leavequery") {
74           
75            @Override
76            public void onClick(AjaxRequestTarget target) {
77                // make query object without selection
78                final QueryFacetsSelection newSelection = new QueryFacetsSelection(selectionModel.getObject().getQuery(), null);
79                onSelectionChanged(newSelection, target);
80            }
81        };
82        link.add(new Label("content", new PropertyModel(selectionModel, "query")));
83        queryContainer.add(link);
84        return queryContainer;
85    }
86   
87    private WebMarkupContainer createFacets(final IModel<QueryFacetsSelection> model, String id) {
88        final WebMarkupContainer facetsContainer = new WebMarkupContainer(id);
89        facetsContainer.add(new AjaxFallbackLink("leaveselection") {
90           
91            @Override
92            public void onClick(AjaxRequestTarget target) {
93                onSelectionChanged(model.getObject(), target);
94            }
95        });
96
97        // create a provider that lists the facet name -> values entries
98        final FacetSelectionProvider facetSelectionProvider = new FacetSelectionProvider(model);
99        facetsContainer.add(new DataView<Map.Entry<String, FacetSelection>>("facet", facetSelectionProvider) {
100           
101            @Override
102            protected void populateItem(final Item<Map.Entry<String, FacetSelection>> item) {
103                final IModel<Map.Entry<String, FacetSelection>> selectionModel = item.getModel();
104                // add a label for the selected facet value(s)
105                final Label valueLabel = new Label("value", new PropertyModel(selectionModel, "value")) {
106                   
107                    @Override
108                    public <C> IConverter<C> getConverter(Class<C> type) {
109                        final String facet = item.getModelObject().getKey();
110                        // converter to render the value(s) nicely
111                        return (IConverter<C>) new SelectionConverter(facet, fieldValueConverterProvider.getConverter(facet));
112                    }
113                   
114                };
115                // add facet name as title attribute so that it becomes available through a tooltip
116                valueLabel.add(new AttributeModifier("title",
117                        new SolrFieldNameModel(new PropertyModel(selectionModel, "key"))));
118                item.add(valueLabel);
119
120                // add a link for removal of the facet value selection
121                item.add(new AjaxFallbackLink("removal") {
122                   
123                    @Override
124                    public void onClick(AjaxRequestTarget target) {
125                        // get a copy of the current selection
126                        final QueryFacetsSelection newSelection = model.getObject().getCopy();
127                        final String facet = selectionModel.getObject().getKey();
128                        // unselect this facet
129                        newSelection.selectValues(facet, null);
130                        onSelectionChanged(newSelection, target);
131                    }
132                });
133            }
134        });
135       
136        return facetsContainer;
137    }
138
139    /**
140     * Gets called if one of the links is clicked and the selection is changed.
141     * This implementation sets the response page to {@link FacetedSearchPage}
142     * with the new selection as its parameters
143     *
144     * @param selection new selection
145     * @param target AJAX target, may be null
146     */
147    protected void onSelectionChanged(QueryFacetsSelection selection, AjaxRequestTarget target) {
148        setResponsePage(FacetedSearchPage.class, paramsConverter.toParameters(selection));
149    }
150   
151    @Override
152    protected void onConfigure() {
153        super.onConfigure();
154       
155        final String queryString = getModelObject().getQuery();
156        final Map<String, FacetSelection> selection = getModelObject().getSelection();
157       
158        query.setVisible(queryString != null && !queryString.isEmpty());
159        facets.setVisible(selection != null && !selection.isEmpty());
160    }
161
162    /**
163     * Converter for string collections, rendering depends on items in
164     * collection (if singleton, show its value; if multiple, comma separated)
165     */
166    private class SelectionConverter implements IConverter<FacetSelection> {
167       
168        private final String facet;
169        private final IConverter<String> valueConverter;
170       
171        public SelectionConverter(String facet, IConverter<String> valueConverter) {
172            this.facet = facet;
173            this.valueConverter = valueConverter;
174        }
175       
176        @Override
177        public FacetSelection convertToObject(String value, Locale locale) throws ConversionException {
178            throw new UnsupportedOperationException("Not supported yet.");
179        }
180       
181        @Override
182        public String convertToString(FacetSelection selection, Locale locale) {
183            switch (selection.getSelectionType()) {
184                case AND:
185                    return getCollectionString(selection, " and ", locale);
186                case OR:
187                    return getCollectionString(selection, " or ", locale);
188                case NOT:
189                    return "not [" + getCollectionString(selection, " or ", locale) + "]";
190                case NOT_EMPTY:
191                    return getAnyValueString();
192                default:
193                    return facet;
194            }
195           
196        }
197       
198        private String getAnyValueString() {
199            if (FacetConstants.FIELD_SEARCH_SERVICE.equals(facet)) {
200                return "Content searchable";
201            }
202            return "any " + facet;
203        }
204       
205        public String getCollectionString(FacetSelection selection, String valueSeparator, Locale locale) {
206            final Collection<String> value = selection.getValues();
207            //TODO: include selection type
208            if (value.isEmpty()) {
209                return "";
210            } else if (value.size() == 1) {
211                return getConvertedValue(value.iterator().next(), locale);
212            } else {
213                final Iterator<String> iterator = value.iterator();
214                final StringBuilder sb = new StringBuilder(getConvertedValue(iterator.next(), locale));
215                while (iterator.hasNext()) {
216                    sb.append(valueSeparator).append(getConvertedValue(iterator.next(), locale));
217                }
218                return sb.toString();
219            }
220        }
221       
222        private String getConvertedValue(String string, Locale locale) {
223            if (valueConverter != null) {
224                final String converted = valueConverter.convertToString(string, locale);
225                if (converted != null) {
226                    return converted;
227                }
228            }
229            return string;
230        }
231       
232    };
233}
Note: See TracBrowser for help on using the repository browser.