source: vlo/branches/to-wicket-1.6/vlo_web_app/src/main/java/eu/clarin/cmdi/vlo/pages/ShowResultPage.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: 23.4 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.StringUtils;
6import eu.clarin.cmdi.vlo.VloSession;
7import eu.clarin.cmdi.vlo.config.VloConfig;
8import eu.clarin.cmdi.vlo.dao.DaoLocator;
9import java.io.InputStreamReader;
10import java.io.StringWriter;
11import java.io.UnsupportedEncodingException;
12import java.net.MalformedURLException;
13import java.net.URL;
14import java.net.URLEncoder;
15import java.util.ArrayList;
16import java.util.Collection;
17import java.util.HashMap;
18import java.util.Iterator;
19import java.util.List;
20import java.util.regex.Pattern;
21import javax.xml.transform.stream.StreamSource;
22import net.sf.saxon.s9api.Processor;
23import net.sf.saxon.s9api.Serializer;
24import net.sf.saxon.s9api.XdmNode;
25import net.sf.saxon.s9api.XsltCompiler;
26import net.sf.saxon.s9api.XsltExecutable;
27import net.sf.saxon.s9api.XsltTransformer;
28import org.apache.solr.common.SolrDocument;
29import org.apache.wicket.Application;
30import org.apache.wicket.Component;
31import org.apache.wicket.request.mapper.parameter.PageParameters;
32import org.apache.wicket.behavior.Behavior;
33import org.apache.wicket.extensions.ajax.markup.html.AjaxLazyLoadPanel;
34import org.apache.wicket.extensions.markup.html.basic.SmartLinkMultiLineLabel;
35import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
36import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
37import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
38import org.apache.wicket.extensions.markup.html.repeater.data.table.HeadersToolbar;
39import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
40import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
41import org.apache.wicket.markup.ComponentTag;
42import org.apache.wicket.markup.MarkupStream;
43import org.apache.wicket.markup.head.IHeaderResponse;
44import org.apache.wicket.markup.head.JavaScriptHeaderItem;
45import org.apache.wicket.markup.html.WebMarkupContainer;
46import org.apache.wicket.markup.html.basic.Label;
47import org.apache.wicket.markup.html.link.BookmarkablePageLink;
48import org.apache.wicket.markup.html.link.ExternalLink;
49import org.apache.wicket.markup.repeater.Item;
50import org.apache.wicket.markup.repeater.RepeatingView;
51import org.apache.wicket.model.IModel;
52import org.apache.wicket.model.ResourceModel;
53import org.apache.wicket.request.Url;
54import org.apache.wicket.request.cycle.RequestCycle;
55import org.apache.wicket.util.encoding.UrlDecoder;
56import org.apache.wicket.util.encoding.UrlEncoder;
57import org.slf4j.Logger;
58import org.slf4j.LoggerFactory;
59
60/**
61 * Page showing VLO search results
62 *
63 * @author keeloo, for the addLandingPage links method and annotations
64 */
65public class ShowResultPage extends BasePage {
66
67    private final static Logger LOG = LoggerFactory.getLogger(ShowResultPage.class);
68    public static final String PARAM_DOC_ID = "docId";
69    public static final String feedbackfromURL = VloConfig.getFeedbackFromUrl();
70
71    private final URL xslFile = getClass().getResource("/cmdi2xhtml.xsl");
72
73    @SuppressWarnings("serial")
74    public ShowResultPage(final PageParameters currentParam) {
75        super(currentParam);
76        //TODO: Is encoding/decoding of the page parameter required (or can it be automated?)
77        final String docId = UrlDecoder.QUERY_INSTANCE.decode(
78                getPageParameters().get(PARAM_DOC_ID).toString(),
79                Application.get().getRequestCycleSettings().getResponseRequestEncoding()); // get current character set from request cycle
80        SolrDocument solrDocument = DaoLocator.getSearchResultsDao().getSolrDocument(docId);
81        if (solrDocument != null) {
82            final SearchPageQuery query = new SearchPageQuery(currentParam);
83
84            // create parameters from the query, and add them with session related parameters
85            PageParameters newParam;
86            newParam = new PageParameters(query.getPageParameters());
87            // add the session persistent parameters
88            newParam.mergeWith(((VloSession)this.getSession()).getVloSessionPageParameters());
89
90            BookmarkablePageLink<String> backLink = new BookmarkablePageLink<String>("backLink", FacetedSearchPage.class, newParam);
91            add(backLink);
92            String href = getHref(docId);
93            if (href != null) {
94                add(new ExternalLink("openBrowserLink", href, new ResourceModel(Resources.OPEN_IN_ORIGINAL_CONTEXT).getObject()));
95            } else {
96                add(new Label("openBrowserLink", new ResourceModel(Resources.ORIGINAL_CONTEXT_NOT_AVAILABLE).getObject()));
97            }
98            addAttributesTable(solrDocument);
99
100            /* If there are any, add the link or links to landing pages
101             * contained in the solr document.
102             */
103            addLandingPageLinks(solrDocument);
104
105            // also, if there are any, add the link or links to search pages
106            addSearchPageLinks(solrDocument);
107
108            // add the rest of the resource links to the result page
109            addResourceLinks(solrDocument);
110
111            addSearchServiceForm(solrDocument);
112            addCompleteCmdiView(solrDocument);
113
114            add(new AjaxLazyLoadPanel("prevNextHeader") {
115
116                @Override
117                public Component getLazyLoadComponent(String markupId) {
118                    return new PrevNextHeaderPanel(markupId, docId, query);
119                }
120
121                @Override
122                public Component getLoadingComponent(String markupId) {
123                    return new PrevNextHeaderPanel(markupId);
124                }
125            });
126        } else {
127            setResponsePage(new ResultNotFoundPage(currentParam));
128        }
129
130        // add the feedback link to the result page
131        addFeedbackLink(currentParam);
132    }
133
134    private String getHref(String linkToOriginalContext) {
135        String result = linkToOriginalContext;
136        if (linkToOriginalContext != null) {
137            if (linkToOriginalContext.startsWith(FacetConstants.TEST_HANDLE_MPI_PREFIX)) {
138                linkToOriginalContext = linkToOriginalContext.replace(FacetConstants.TEST_HANDLE_MPI_PREFIX, FacetConstants.HANDLE_MPI_PREFIX);
139            }
140            if (linkToOriginalContext.startsWith(FacetConstants.HANDLE_MPI_PREFIX)) {
141                result = VloConfig.getIMDIBrowserUrl(linkToOriginalContext);
142            } else {
143                try {
144                    new URL(linkToOriginalContext);
145                } catch (MalformedURLException e) {
146                    LOG.debug("Link to original context is incorrect:", e);
147                    result = null;
148                }
149            }
150        }
151        return result;
152    }
153
154    /*
155     * Based on the solr document, create a table of meta data attribute and value pairs
156     */
157    private void addAttributesTable(final SolrDocument solrDocument) {
158        // because of FIELD_LANGUAGE_LINK, remove the FIELD_LANDGUAGE facet
159        solrDocument.remove(FacetConstants.FIELD_LANGUAGE);
160        /* Use the data provider from the solrDocument object as a provider
161         * for the table to be instantiated here.
162         */
163        DocumentAttributesDataProvider attributeProvider = new DocumentAttributesDataProvider(solrDocument);
164
165        DataTable table;
166        /* Create table: use the provider, and pass a method to create the
167         * columns.
168         */
169        table = new DataTable("attributesTable", createAttributesColumns(), attributeProvider, 250);
170        // associate css with table
171        table.setTableBodyCss("attributesTbody");
172        table.addTopToolbar(new HeadersToolbar(table, null));
173        // add table to page
174        add(table);
175    }
176
177    /**
178     * Create the columns for the table.
179     *
180     * Create one column for the attributes and one column for their values.
181     *
182     * @newParam
183     */
184    private List<IColumn> createAttributesColumns() {
185        List<IColumn> columns = new ArrayList<IColumn>();
186
187        // create the column for the attribute names
188        IColumn column = null;
189        column = new PropertyColumn<Object, Object>(new ResourceModel(Resources.FIELD), "field") {
190
191            @Override
192            public String getCssClass() {
193                return "attribute";
194            }
195        };
196        columns.add(column);
197
198        // create the column for the values of the attributes
199        column = new AbstractColumn<DocumentAttribute, String>(new ResourceModel(Resources.VALUE)) {
200            @Override
201            public void populateItem(Item<ICellPopulator<DocumentAttribute>> cellItem,
202                    String componentId, IModel<DocumentAttribute> rowModel) {
203
204                /*
205                 * While in the data for the table, the values (for the
206                 * description) attribute are structured. Creating a single
207                 * attribute, these values are collapsed. Refer to the
208                 *
209                 * DocumentAttribute
210                 *
211                 * class.
212                 */
213                DocumentAttribute attribute = rowModel.getObject();
214
215                if (attribute.getField().equals(FacetConstants.FIELD_LANGUAGES)) {
216                    cellItem.add(new SmartLinkMultiLineLabel(componentId, attribute.getValue()) {
217                        @Override
218                        public void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag) {
219                            setEscapeModelStrings(false);
220                            CharSequence body = getDefaultModelObjectAsString();
221                            replaceComponentTagBody(markupStream, openTag, body);
222                        }
223                    });
224                } else if (attribute.getField().equals(FacetConstants.FIELD_COMPLETE_METADATA)) {
225                    cellItem.add(new SmartLinkMultiLineLabel(componentId, attribute.getValue()) {
226                        @Override
227                        public void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag) {
228                            setEscapeModelStrings(false);
229                            CharSequence body = getDefaultModelObjectAsString();
230                            replaceComponentTagBody(markupStream, openTag, "<a href=\"" + body + "\">" + body + "</a>");
231                        }
232                    });
233                } else {
234                    cellItem.add(new SmartLinkMultiLineLabel(componentId, attribute.getValue()) {
235                        @Override
236                        public void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag) {
237                            CharSequence body = StringUtils.toMultiLineHtml(getDefaultModelObjectAsString());
238                            replaceComponentTagBody(markupStream, openTag, getSmartLink(body));
239                        }
240                    });
241                }
242            }
243
244            @Override
245            public String getCssClass() {
246                return "attributeValue";
247            }
248        };
249        columns.add(column);
250
251        return columns;
252    }
253
254    /**
255     * Add landing page links to the result page.
256     *
257     * @newParam solrDocument the document to get the links from
258     */
259    private void addLandingPageLinks(SolrDocument solrDocument) {
260
261        Label oneLandingPageText;
262        oneLandingPageText = new Label("oneLandingPage",
263                new ResourceModel(Resources.LANDING_PAGE).getObject() + ":");
264        this.add(oneLandingPageText);
265
266        Label moreLandingPagesText;
267        moreLandingPagesText = new Label("moreLandingPages",
268                new ResourceModel(Resources.LANDING_PAGES).getObject() + ":");
269        this.add(moreLandingPagesText);
270
271        RepeatingView repeatingView = new RepeatingView("landingPageList");
272        add(repeatingView);
273
274        /*
275         * Depending on the number of links to be shown, at most one of the
276         * labels in the accompanying HTML page that is subject to Wicket is
277         * made visible.
278         */
279        if (!solrDocument.containsKey(FacetConstants.FIELD_LANDINGPAGE)) {
280
281            /* Since there are no links to be shown, make both labels defined in
282             * the page invisible
283             */
284            oneLandingPageText.setVisible(false);
285            moreLandingPagesText.setVisible(false);
286        } else {
287            //  make one of the two labels invisible
288
289            Collection<Object> landingPages
290                    = solrDocument.getFieldValues(FacetConstants.FIELD_LANDINGPAGE);
291            if (landingPages.size() > 1) {
292
293                // the list will contain more than one landing page link
294                oneLandingPageText.setVisible(false);
295                moreLandingPagesText.setVisible(true);
296            } else {
297                // the list will contain exactly one landing page link.
298                oneLandingPageText.setVisible(true);
299                moreLandingPagesText.setVisible(false);
300            }
301
302            // generate the list of links
303            for (Iterator<Object> it = landingPages.iterator(); it.hasNext();) {
304                final Object landingPage;
305                landingPage = it.next();
306
307                // add a link to the list
308                repeatingView.add(
309                        new AjaxLazyLoadPanel(repeatingView.newChildId()) {
310                            @Override
311                            public Component getLazyLoadComponent(String markupId) {
312                                String landingPageLink;
313                                landingPageLink = landingPage.toString();
314
315                                // create a panel for the link
316                                return new LandingPageLinkPanel(markupId,
317                                        landingPage.toString());
318                            }
319                        });
320            }
321        }
322    }
323
324    /**
325     * Add search page links to the result page.
326     *
327     * @newParam solrDocument the document to get the links from
328     */
329    private void addSearchPageLinks(SolrDocument solrDocument) {
330
331        Label oneSearchPageText;
332        oneSearchPageText = new Label("oneSearchPage",
333                new ResourceModel(Resources.SEARCH_PAGE).getObject() + ":");
334        this.add(oneSearchPageText);
335
336        Label moreSearchPagesText;
337        moreSearchPagesText = new Label("moreSearchPages",
338                new ResourceModel(Resources.SEARCH_PAGES).getObject() + ":");
339        this.add(moreSearchPagesText);
340
341        RepeatingView repeatingView = new RepeatingView("searchPageList");
342        add(repeatingView);
343
344        /*
345         * Depending on the number of links to be shown, at most one of the
346         * labels in the accompanying HTML page that is subject to Wicket is
347         * made visible.
348         */
349        if (!solrDocument.containsKey(FacetConstants.FIELD_SEARCHPAGE)) {
350
351            /* Since there are no links to be shown, make both labels defined in
352             * the page invisible
353             */
354            oneSearchPageText.setVisible(false);
355            moreSearchPagesText.setVisible(false);
356        } else {
357            //  make one of the two labels invisible
358
359            Collection<Object> searchPages
360                    = solrDocument.getFieldValues(FacetConstants.FIELD_SEARCHPAGE);
361            if (searchPages.size() > 1) {
362
363                // the list will contain more than one landing page link
364                oneSearchPageText.setVisible(false);
365                moreSearchPagesText.setVisible(true);
366            } else {
367                // the list will contain exactly one landing page link.
368                oneSearchPageText.setVisible(true);
369                moreSearchPagesText.setVisible(false);
370            }
371
372            // generate the list of links
373            for (Iterator<Object> it = searchPages.iterator(); it.hasNext();) {
374                final Object searchPage;
375                searchPage = it.next();
376
377                // add a link to the list
378                repeatingView.add(
379                        new AjaxLazyLoadPanel(repeatingView.newChildId()) {
380                            @Override
381                            public Component getLazyLoadComponent(String markupId) {
382                                String searchPageLink;
383                                searchPageLink = searchPage.toString();
384
385                                // create a panel for the link
386                                return new SearchPageLinkPanel(markupId,
387                                        searchPage.toString());
388                            }
389                        });
390            }
391        }
392    }
393
394    /**
395     * Add links to resources other than search or landing pages to the result
396     * page.
397     *
398     * @newParam solrDocument the document to get the links from
399     */
400    private void addResourceLinks(SolrDocument solrDocument) {
401        RepeatingView repeatingView = new RepeatingView("resourceList");
402        add(repeatingView);
403        if (solrDocument.containsKey(FacetConstants.FIELD_RESOURCE)) {
404            Collection<Object> resources = solrDocument.getFieldValues(FacetConstants.FIELD_RESOURCE);
405            if (resources.size() > 1) {
406                repeatingView.add(new Label(repeatingView.newChildId(), new ResourceModel(Resources.RESOURCE_PL)));
407            } else {
408                repeatingView.add(new Label(repeatingView.newChildId(), new ResourceModel(Resources.RESOURCE)));
409            }
410            for (Object resource : resources) {
411                String[] split = resource.toString().split(Pattern.quote(FacetConstants.FIELD_RESOURCE_SPLIT_CHAR), 2);
412                final String mimeType = split[0];
413                final String resourceLink = split[1];
414                repeatingView.add(new AjaxLazyLoadPanel(repeatingView.newChildId()) {
415
416                    @Override
417                    public Component getLazyLoadComponent(String markupId) {
418                        return new ResourceLinkPanel(markupId, mimeType, resourceLink);
419                    }
420                });
421            }
422        } else {
423            repeatingView.add(new Label(repeatingView.newChildId(), new ResourceModel(Resources.NO_RESOURCE_FOUND)));
424        }
425    }
426
427    private void addFeedbackLink(final PageParameters parameters) {
428
429        PageParameters newParam = new PageParameters(parameters);
430        // add the session persistent paremeters
431        newParam.mergeWith(((VloSession)this.getSession()).getVloSessionPageParameters());
432
433        final RequestCycle reqCycle = getRequestCycle();
434        // the following will not be necessary anymore
435        // final Url reqUrl = Url.parse(reqCycle.urlFor(ShowResultPage.class, newParam.convert()));
436        final Url reqUrl = Url.parse(reqCycle.urlFor(ShowResultPage.class, newParam));
437        String thisURL = reqCycle.getUrlRenderer().renderFullUrl(reqUrl);
438
439        try {
440            thisURL = URLEncoder.encode(thisURL, "UTF-8");
441        } catch (UnsupportedEncodingException e) {
442            LOG.error(e.toString());
443        }
444
445        // Image resourceImg = new Image("feedbackImage", FEEDBACK_IMAGE.getResource());
446        // String title = "Report an error";
447        // resourceImg.add(new SimpleAttributeModifier("title", title));
448        // resourceImg.add(new SimpleAttributeModifier("alt", title));
449        String href = getHref(feedbackfromURL + thisURL);
450        String name = feedbackfromURL + thisURL;
451        ExternalLink link = new ExternalLink("feedbackLink", href, "found an error?");
452        // link.add(resourceImg);
453        // add(new Label("feedbackLabel", "Found an error?"));
454        add(link);
455    }
456
457    public static BookmarkablePageLink<ShowResultPage> createBookMarkableLink(String linkId, SearchPageQuery query, String docId) {
458
459        // create new page parameters from the query parameters and the session related ones
460        PageParameters newParam;
461        newParam = new PageParameters(query.getPageParameters());
462        // add the session persistent parameters
463        // newParam.add(((VloSession)this.getSession()).getVloSessionPageParameters());
464        newParam.add(ShowResultPage.PARAM_DOC_ID, UrlEncoder.QUERY_INSTANCE.encode(
465                docId,
466                Application.get().getRequestCycleSettings().getResponseRequestEncoding())); // get current character set from request cycle
467
468        BookmarkablePageLink<ShowResultPage> docLink = new BookmarkablePageLink<ShowResultPage>(linkId, ShowResultPage.class,
469                newParam);
470        return docLink;
471    }
472
473    /**
474     * Add contentSearch form (FCS)
475     *
476     * @newParam solrDocument
477     */
478    private void addSearchServiceForm(final SolrDocument solrDocument) {
479        final WebMarkupContainer contentSearchContainer = new WebMarkupContainer("contentSearch");
480        add(contentSearchContainer);
481
482        if (solrDocument.containsKey(FacetConstants.FIELD_SEARCH_SERVICE)) {
483            try {
484                // building map (CQL endpoint -> List with resource ID)
485                HashMap<String, List<String>> aggregrationContextMap = new HashMap<String, List<String>>();
486                List<String> idList = new ArrayList<String>();
487                idList.add(solrDocument.getFirstValue(FacetConstants.FIELD_ID).toString());
488                aggregrationContextMap.put(solrDocument.getFirstValue(FacetConstants.FIELD_SEARCH_SERVICE).toString(), idList);
489                Label contentSearchLabel = new Label("contentSearchForm", HtmlFormCreator.getContentSearchForm(aggregrationContextMap, "Plain text search via Federated Content Search"));
490                contentSearchLabel.setEscapeModelStrings(false);
491                contentSearchContainer.add(contentSearchLabel);
492            } catch (UnsupportedEncodingException uee) {
493                contentSearchContainer.setVisible(false);
494            }
495        } else {
496            contentSearchContainer.setVisible(false);
497        }
498    }
499
500    /**
501     * Add complete CMDI view
502     *
503     * @newParam solrDocument
504     */
505    private void addCompleteCmdiView(final SolrDocument solrDocument) {
506        StringWriter strWriter = new StringWriter();
507
508        final Processor proc = new Processor(false);
509        final XsltCompiler comp = proc.newXsltCompiler();
510
511        try {
512            final XsltExecutable exp = comp.compile(new StreamSource(xslFile.getFile()));
513            final XdmNode source = proc.newDocumentBuilder().build(
514                    new StreamSource(new InputStreamReader(new URL(solrDocument.getFirstValue(FacetConstants.FIELD_COMPLETE_METADATA).toString()).openStream())));
515            final Serializer out = new Serializer();
516            out.setOutputProperty(Serializer.Property.METHOD, "html");
517            out.setOutputProperty(Serializer.Property.INDENT, "yes");
518            out.setOutputProperty(Serializer.Property.ENCODING, "UTF-8");
519            out.setOutputWriter(strWriter);
520            final XsltTransformer trans = exp.load();
521
522            trans.setInitialContextNode(source);
523            trans.setDestination(out);
524            trans.transform();
525        } catch (Exception e) {
526            LOG.error("Couldn't create CMDI metadata: " + e.getMessage());
527            strWriter = new StringWriter().append("<b>Could not load complete CMDI metadata</b>");
528        }
529
530        Label completeCmdiLabel = new Label("completeCmdi", strWriter.toString());
531        completeCmdiLabel.setEscapeModelStrings(false);
532        add(completeCmdiLabel);
533
534        // remove complete CMDI view on page load
535        add(new Behavior() {
536            private static final long serialVersionUID = 1865219352602175954L;
537
538            public void renderHead(IHeaderResponse response) {
539                response.render(JavaScriptHeaderItem.forScript("toogleDiv('completeCmdi', 'toogleLink')", null));
540            }
541        });
542    }
543}
Note: See TracBrowser for help on using the repository browser.