source: vlo/trunk/vlo-web-app/src/main/java/eu/clarin/cmdi/vlo/wicket/pages/RecordPage.java @ 6305

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

checking for parts by means of count field, not retrieving all hasPart field values
Refs #382

File size: 13.6 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.pages;
18
19import eu.clarin.cmdi.vlo.wicket.model.PermaLinkModel;
20import eu.clarin.cmdi.vlo.FacetConstants;
21import eu.clarin.cmdi.vlo.VloWebAppParameters;
22import eu.clarin.cmdi.vlo.pojo.QueryFacetsSelection;
23import eu.clarin.cmdi.vlo.pojo.SearchContext;
24import eu.clarin.cmdi.vlo.service.FieldFilter;
25import eu.clarin.cmdi.vlo.service.PageParametersConverter;
26import eu.clarin.cmdi.vlo.wicket.HighlightSearchTermBehavior;
27import eu.clarin.cmdi.vlo.wicket.components.SolrFieldLabel;
28import eu.clarin.cmdi.vlo.wicket.model.CollectionListModel;
29import eu.clarin.cmdi.vlo.wicket.model.HandleLinkModel;
30import eu.clarin.cmdi.vlo.wicket.model.NullFallbackModel;
31import eu.clarin.cmdi.vlo.wicket.model.SearchContextModel;
32import eu.clarin.cmdi.vlo.wicket.model.SolrDocumentModel;
33import eu.clarin.cmdi.vlo.wicket.model.SolrFieldModel;
34import eu.clarin.cmdi.vlo.wicket.model.SolrFieldStringModel;
35import eu.clarin.cmdi.vlo.wicket.model.UrlFromStringModel;
36import eu.clarin.cmdi.vlo.wicket.model.XsltModel;
37import eu.clarin.cmdi.vlo.wicket.panels.BreadCrumbPanel;
38import eu.clarin.cmdi.vlo.wicket.panels.ContentSearchFormPanel;
39import eu.clarin.cmdi.vlo.wicket.panels.TogglePanel;
40import eu.clarin.cmdi.vlo.wicket.panels.TopLinksPanel;
41import eu.clarin.cmdi.vlo.wicket.panels.record.FieldsTablePanel;
42import eu.clarin.cmdi.vlo.wicket.panels.record.HierarchyPanel;
43import eu.clarin.cmdi.vlo.wicket.panels.record.RecordNavigationPanel;
44import eu.clarin.cmdi.vlo.wicket.panels.record.ResourceLinksPanel;
45import eu.clarin.cmdi.vlo.wicket.provider.DocumentFieldsProvider;
46import java.util.List;
47import org.apache.solr.common.SolrDocument;
48import org.apache.wicket.Component;
49import org.apache.wicket.RestartResponseException;
50import org.apache.wicket.Session;
51import org.apache.wicket.ajax.AjaxRequestTarget;
52import org.apache.wicket.markup.head.CssHeaderItem;
53import org.apache.wicket.markup.head.IHeaderResponse;
54import org.apache.wicket.markup.html.WebMarkupContainer;
55import org.apache.wicket.markup.html.basic.Label;
56import org.apache.wicket.markup.html.link.ExternalLink;
57import org.apache.wicket.markup.html.list.ListItem;
58import org.apache.wicket.markup.html.list.ListView;
59import org.apache.wicket.model.IModel;
60import org.apache.wicket.model.Model;
61import org.apache.wicket.model.PropertyModel;
62import org.apache.wicket.model.StringResourceModel;
63import org.apache.wicket.request.mapper.parameter.PageParameters;
64import org.apache.wicket.request.resource.CssResourceReference;
65import org.apache.wicket.request.resource.ResourceReference;
66import org.apache.wicket.spring.injection.annot.SpringBean;
67
68/**
69 *
70 * @author twagoo
71 */
72public class RecordPage extends VloBasePage<SolrDocument> {
73
74    private final static ResourceReference CMDI_HTML_CSS = new CssResourceReference(RecordPage.class, "cmdi.css");
75
76    @SpringBean(name = "documentParamsConverter")
77    private PageParametersConverter<SolrDocument> documentParamConverter;
78    @SpringBean(name = "queryParametersConverter")
79    private PageParametersConverter<QueryFacetsSelection> selectionParametersConverter;
80    @SpringBean(name = "searchContextParamsConverter")
81    private PageParametersConverter<SearchContext> contextParamConverter;
82    @SpringBean(name = "basicPropertiesFilter")
83    private FieldFilter basicPropertiesFilter;
84    @SpringBean(name = "technicalPropertiesFilter")
85    private FieldFilter technicalPropertiesFilter;
86    @SpringBean(name = "documentFieldOrder")
87    private List<String> fieldOrder;
88
89    private final IModel<SearchContext> navigationModel;
90    private final IModel<QueryFacetsSelection> selectionModel;
91
92    /**
93     * Constructor that derives document and selection models from page
94     * parameters (external request or through the framework)
95     *
96     * @param params
97     */
98    public RecordPage(PageParameters params) {
99        super(params);
100
101        // get search context from params if available
102        final SearchContext searchContext = contextParamConverter.fromParameters(params);
103        if (searchContext instanceof SearchContextModel) {
104            this.navigationModel = (SearchContextModel) (searchContext);
105        } else if (searchContext != null) {
106            this.navigationModel = Model.of(searchContext);
107        } else {
108            this.navigationModel = null;
109        }
110
111        // get selection from context or parameters
112        if (navigationModel == null) {
113            final QueryFacetsSelection selection = selectionParametersConverter.fromParameters(params);
114            selectionModel = Model.of(selection);
115        } else {
116            selectionModel = new PropertyModel(navigationModel, "selection");
117        }
118
119        // get document from parameters
120        final SolrDocument document = documentParamConverter.fromParameters(params);
121        if (null == document) {
122            Session.get().error(String.format("Document with ID %s could not be found", params.get(VloWebAppParameters.DOCUMENT_ID)));
123            throw new RestartResponseException(new FacetedSearchPage(selectionModel));
124        } else {
125            setModel(new SolrDocumentModel(document));
126        }
127
128        addComponents();
129        add(new HighlightSearchTermBehavior());
130    }
131
132    private void addComponents() {
133        // Navigation
134        add(createNavigation("navigation"));
135
136        final WebMarkupContainer topNavigation = new WebMarkupContainer("topnavigation");
137        topNavigation.setOutputMarkupId(true);
138        add(topNavigation);
139
140        topNavigation.add(new BreadCrumbPanel("breadcrumbs", selectionModel));
141        topNavigation.add(createPermalink("permalink", topNavigation));
142
143        // General information section
144        add(new SolrFieldLabel("name", getModel(), FacetConstants.FIELD_NAME, getString("recordpage.unnamedrecord")));
145        add(createLandingPageLink("landingPageLink"));
146        add(new FieldsTablePanel("documentProperties", new DocumentFieldsProvider(getModel(), basicPropertiesFilter, fieldOrder)));
147
148        // Resources section
149        add(new ResourceLinksPanel("resources", new SolrFieldModel<String>(getModel(), FacetConstants.FIELD_RESOURCE)));
150
151        // Technical section
152        add(createCmdiContent("cmdi"));
153        add(createTechnicalDetailsPanel("technicalProperties"));
154
155        add(createHierarchyPanel("recordtree"));
156
157        createSearchLinks("searchlinks");
158    }
159
160    private Component createNavigation(final String id) {
161        if (navigationModel != null) {
162            // Add a panel that shows the index of the current record in the
163            // resultset and allows for forward/backward navigation
164            return new RecordNavigationPanel(id, navigationModel) {
165
166                @Override
167                protected void onConfigure() {
168                    final SearchContext context = navigationModel.getObject();
169                    setVisible(context != null && context.getResultCount() > 1);
170                }
171
172            };
173        } else {
174            // If no context model is available (i.e. when coming from a bookmark
175            // or external link, do not show the navigation panel
176            final WebMarkupContainer navigationDummy = new WebMarkupContainer(id);
177            navigationDummy.setVisible(false);
178            return navigationDummy;
179        }
180    }
181
182    private TopLinksPanel createPermalink(String id, final WebMarkupContainer topNavigation) {
183        return new TopLinksPanel(id, new PermaLinkModel(getPageClass(), selectionModel, getModel())) {
184
185            @Override
186            protected void onChange(AjaxRequestTarget target) {
187                if (target != null) {
188                    target.add(topNavigation);
189                }
190            }
191
192        };
193    }
194
195    private ExternalLink createLandingPageLink(String id) {
196        final IModel<String> landingPageHrefModel
197                // wrap in model that transforms handle links
198                = new HandleLinkModel(
199                        // get landing page from document
200                        new SolrFieldStringModel(getModel(), FacetConstants.FIELD_LANDINGPAGE));
201        // add landing page link
202        final ExternalLink landingPageLink = new ExternalLink(id, landingPageHrefModel) {
203
204            @Override
205            protected void onConfigure() {
206                super.onConfigure();
207                setVisible(landingPageHrefModel.getObject() != null);
208            }
209
210        };
211        return landingPageLink;
212    }
213
214    private void createSearchLinks(String id) {
215        final SolrFieldModel<String> searchPageModel = new SolrFieldModel<String>(getModel(), FacetConstants.FIELD_SEARCHPAGE);
216        final SolrFieldModel<String> searchServiceModel = new SolrFieldModel<String>(getModel(), FacetConstants.FIELD_SEARCH_SERVICE);
217        add(new WebMarkupContainer(id) {
218            {
219                //Add search page links (can be multiple)
220                add(new ListView<String>("searchPage", new CollectionListModel<String>(searchPageModel)) {
221
222                    @Override
223                    protected void populateItem(ListItem item) {
224                        item.add(new ExternalLink("searchLink", item.getModel()));
225                    }
226                });
227
228                // We assume there can be multiple content search endpoints too
229                add(new ListView<String>("contentSearch", new CollectionListModel<String>(searchServiceModel)) {
230
231                    @Override
232                    protected void populateItem(ListItem<String> item) {
233                        item.add(new ContentSearchFormPanel("fcsForm", RecordPage.this.getModel(), item.getModel()));
234                    }
235                });
236            }
237
238            @Override
239
240            protected void onConfigure() {
241                super.onConfigure();
242                setVisible(searchPageModel.getObject() != null || searchServiceModel.getObject() != null);
243            }
244
245        });
246    }
247
248    private Component createCmdiContent(String id) {
249
250        final IModel<String> locationModel = new SolrFieldStringModel(getModel(), FacetConstants.FIELD_FILENAME);
251        final UrlFromStringModel locationUrlModel = new UrlFromStringModel(locationModel);
252        final TogglePanel togglePanel = new TogglePanel(id, Model.of("Show all metadata fields"), Model.of("Hide all metadata fields")) {
253
254            @Override
255            protected Component createContent(String id) {
256                final Label cmdiContentLabel = new Label(id, new XsltModel(locationUrlModel));
257                cmdiContentLabel.setEscapeModelStrings(false);
258                return cmdiContentLabel;
259            }
260        };
261        // highlight search terms when panel becomes visible
262        togglePanel.add(new HighlightSearchTermBehavior());
263        return togglePanel;
264    }
265
266    private TogglePanel createTechnicalDetailsPanel(String id) {
267        return new TogglePanel(id, Model.of("Show technical details"), Model.of("Hide technical details")) {
268
269            @Override
270            protected Component createContent(String id) {
271                return new FieldsTablePanel(id, new DocumentFieldsProvider(getModel(), technicalPropertiesFilter, fieldOrder));
272            }
273        };
274    }
275
276    private HierarchyPanel createHierarchyPanel(String id) {
277        return new HierarchyPanel(id, getModel()) {
278
279            @Override
280            protected void onConfigure() {
281                final SolrDocument document = getModel().getObject();
282                final Object partCount = document.getFieldValue(FacetConstants.FIELD_HAS_PART_COUNT);
283                final boolean hasHierarchy // has known parent or children
284                        = null != document.getFieldValue(FacetConstants.FIELD_IS_PART_OF) // has parent
285                        || (null != partCount && !Integer.valueOf(0).equals(partCount)); // children count != 0
286
287                // only show hierarchy panel if there's anything to show
288                setVisible(hasHierarchy);
289            }
290
291        };
292    }
293
294    @Override
295    public void detachModels() {
296        super.detachModels();
297        if (navigationModel != null) {
298            // not passed to parent
299            navigationModel.detach();
300        }
301    }
302
303    @Override
304    public IModel<String> getTitleModel() {
305        // Put the name of the record in the page title
306        return new StringResourceModel("recordpage.title",
307                new NullFallbackModel(new SolrFieldStringModel(getModel(), FacetConstants.FIELD_NAME), getString("recordpage.unnamedrecord")),
308                DEFAULT_PAGE_TITLE);
309    }
310
311    @Override
312    public IModel<String> getPageDescriptionModel() {
313        return new SolrFieldStringModel(getModel(), FacetConstants.FIELD_DESCRIPTION);
314    }
315
316    @Override
317    public IModel<String> getCanonicalUrlModel() {
318        // omit query in link for canonical URL (record page gets same canonical
319        // URL regardless of search term)
320        return new PermaLinkModel(getPageClass(), null, getModel());
321    }
322
323    @Override
324    public void renderHead(IHeaderResponse response) {
325        super.renderHead(response);
326        // add styling for CMDI to HTML transformation output
327        response.render(CssHeaderItem.forReference(CMDI_HTML_CSS));
328    }
329
330}
Note: See TracBrowser for help on using the repository browser.