source: vlo/trunk/vlo_web_app/src/main/java/eu/clarin/cmdi/vlo/pages/ShowResultPage.java @ 4004

Last change on this file since 4004 was 4004, checked in by keeloo, 11 years ago

commit for 2.17 beta

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