source: vlo/branches/to-wicket-1.6-twagoo/vlo_web_app/src/main/java/eu/clarin/cmdi/vlo/pages/ShowResultPage.java @ 4212

Last change on this file since 4212 was 4212, checked in by twagoo, 10 years ago

Branched off keeloo's wicket-6 conversion branch.
Applied a number of fixes to make code properly compilable, runnable (app still doesn't start properly).
To be merged back with keeloo's work.

File size: 22.9 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.VloPageParameters;
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.protocol.http.RequestUtils;
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 merge them with session related parameters
85            VloPageParameters newParam; 
86            newParam = new VloPageParameters (query.getPageParameters());
87           
88            BookmarkablePageLink<String> backLink = new BookmarkablePageLink<String>("backLink", FacetedSearchPage.class, newParam);
89            add(backLink);
90            String href = getHref(docId);
91            if (href != null) {
92                add(new ExternalLink("openBrowserLink", href, new ResourceModel(Resources.OPEN_IN_ORIGINAL_CONTEXT).getObject()));
93            } else {
94                add(new Label("openBrowserLink", new ResourceModel(Resources.ORIGINAL_CONTEXT_NOT_AVAILABLE).getObject()));
95            }
96            addAttributesTable(solrDocument);
97           
98            /* If there are any, add the link or links to landing pages
99             * contained in the solr document.
100             */
101            addLandingPageLinks(solrDocument);
102           
103            // also, if there are any, add the link or links to search pages
104            addSearchPageLinks(solrDocument);
105
106            // add the rest of the resource links to the result page
107            addResourceLinks(solrDocument);
108           
109            addSearchServiceForm(solrDocument);
110            addCompleteCmdiView(solrDocument);
111           
112            add(new AjaxLazyLoadPanel("prevNextHeader") {
113
114                @Override
115                public Component getLazyLoadComponent(String markupId) {
116                    return new PrevNextHeaderPanel(markupId, docId, query);
117                }
118
119                @Override
120                public Component getLoadingComponent(String markupId) {
121                    return new PrevNextHeaderPanel(markupId);
122                }
123            });
124        } else {
125            setResponsePage(new ResultNotFoundPage(currentParam));
126        }
127
128        // add the feedback link to the result page
129        addFeedbackLink(currentParam);
130    }
131
132    private String getHref(String linkToOriginalContext) {
133        String result = linkToOriginalContext;
134        if (linkToOriginalContext != null) {
135            if (linkToOriginalContext.startsWith(FacetConstants.TEST_HANDLE_MPI_PREFIX)) {
136                linkToOriginalContext = linkToOriginalContext.replace(FacetConstants.TEST_HANDLE_MPI_PREFIX, FacetConstants.HANDLE_MPI_PREFIX);
137            }
138            if (linkToOriginalContext.startsWith(FacetConstants.HANDLE_MPI_PREFIX)) {
139                result = VloConfig.getIMDIBrowserUrl(linkToOriginalContext);
140            } else {
141                try {
142                    new URL(linkToOriginalContext);
143                } catch (MalformedURLException e) {
144                    LOG.debug("Link to original context is incorrect:", e);
145                    result = null;
146                }
147            }
148        }
149        return result;
150    }
151
152    /*
153     * Based on the solr document, create a table of meta data attribute and value pairs
154     */
155    private void addAttributesTable(final SolrDocument solrDocument) {
156        // because of FIELD_LANGUAGE_LINK, remove the FIELD_LANDGUAGE facet
157        solrDocument.remove(FacetConstants.FIELD_LANGUAGE);
158        /* Use the data provider from the solrDocument object as a provider
159         * for the table to be instantiated here.
160         */
161        DocumentAttributesDataProvider attributeProvider = new DocumentAttributesDataProvider(solrDocument);
162
163        DataTable table;
164        /* Create table: use the provider, and pass a method to create the
165         * columns.
166         */
167        table = new DataTable("attributesTable", createAttributesColumns(), attributeProvider, 250);
168        // associate css with table
169        table.setTableBodyCss("attributesTbody");
170        table.addTopToolbar(new HeadersToolbar(table, null)); 
171        // add table to page
172        add(table);
173    }
174
175    /**
176     * Create the columns for the table.
177     *
178     * Create one column for the attributes and one column for their values.
179     *
180     * @newParam
181     */
182    private List<IColumn> createAttributesColumns() {
183        List<IColumn> columns = null;
184
185        // create the column for the attribute names
186        IColumn column = null;
187        column = new PropertyColumn<Object,Object>(new ResourceModel(Resources.FIELD), "field") {
188
189            @Override
190            public String getCssClass() {
191                return "attribute";
192            }
193        };
194        columns.add (column);
195
196        // create the column for the values of the attributes
197        column = new AbstractColumn<DocumentAttribute, String>(new ResourceModel(Resources.VALUE)) {
198            @Override
199            public void populateItem(Item<ICellPopulator<DocumentAttribute>> cellItem,
200                    String componentId, IModel<DocumentAttribute> rowModel) {
201
202                /*
203                 * While in the data for the table, the values (for the
204                 * description) attribute are structured. Creating a single
205                 * attribute, these values are collapsed. Refer to the
206                 *
207                 * DocumentAttribute
208                 *
209                 * class.
210                 */
211                DocumentAttribute attribute = rowModel.getObject();
212
213                if (attribute.getField().equals(FacetConstants.FIELD_LANGUAGES)) {
214                    cellItem.add(new SmartLinkMultiLineLabel(componentId, attribute.getValue()) {
215                        @Override
216                        public void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag) {
217                            setEscapeModelStrings(false);
218                            CharSequence body = getDefaultModelObjectAsString();
219                            replaceComponentTagBody(markupStream, openTag, body);
220                        }
221                    });
222                } else if (attribute.getField().equals(FacetConstants.FIELD_COMPLETE_METADATA)) {
223                    cellItem.add(new SmartLinkMultiLineLabel(componentId, attribute.getValue()) {
224                        @Override
225                        public void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag) {
226                            setEscapeModelStrings(false);
227                            CharSequence body = getDefaultModelObjectAsString();
228                            replaceComponentTagBody(markupStream, openTag, "<a href=\"" + body + "\">" + body + "</a>");
229                        }
230                    });
231                } else {
232                    cellItem.add(new SmartLinkMultiLineLabel(componentId, attribute.getValue()) {
233                        @Override
234                        public void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag) {
235                            CharSequence body = StringUtils.toMultiLineHtml(getDefaultModelObjectAsString());
236                            replaceComponentTagBody(markupStream, openTag, getSmartLink(body));
237                        }
238                    });
239                }
240            }
241
242            @Override
243            public String getCssClass() {
244                return "attributeValue";
245            }
246        };
247        columns.add (column);
248
249        return columns;
250    }
251   
252    /**
253     * Add landing page links to the result page.
254     *
255     * @newParam 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     * @newParam 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     * @newParam 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       
427        // create VloPageParameters in orde to be able to convert to old style parameters
428        VloPageParameters newParam = new VloPageParameters (parameters);
429       
430        String thisURL = RequestUtils.toAbsolutePath(RequestCycle.get().urlFor(ShowResultPage.class, newParam.convert()).toString(),null);
431        try {
432            thisURL = URLEncoder.encode(thisURL,"UTF-8");
433        } catch (UnsupportedEncodingException e) {
434            LOG.error(e.toString());
435        }
436       
437        // Image resourceImg = new Image("feedbackImage", FEEDBACK_IMAGE.getResource());
438        // String title = "Report an error";
439        // resourceImg.add(new SimpleAttributeModifier("title", title));
440        // resourceImg.add(new SimpleAttributeModifier("alt", title));
441        String href = getHref(feedbackfromURL+thisURL);
442        String name = feedbackfromURL+thisURL;
443        ExternalLink link = new ExternalLink("feedbackLink", href, "found an error?");
444        // link.add(resourceImg);
445        // add(new Label("feedbackLabel", "Found an error?"));
446        add(link);
447    }
448
449    public static BookmarkablePageLink<ShowResultPage> createBookMarkableLink(String linkId, SearchPageQuery query, String docId) {
450
451        // create new page parameters from the query parameters and the session related ones
452        VloPageParameters newParam;
453        newParam = new VloPageParameters(query.getPageParameters());
454        newParam.add(ShowResultPage.PARAM_DOC_ID, UrlEncoder.QUERY_INSTANCE.encode(
455                docId, 
456                Application.get().getRequestCycleSettings().getResponseRequestEncoding())); // get current character set from request cycle
457
458        BookmarkablePageLink<ShowResultPage> docLink = new BookmarkablePageLink<ShowResultPage>(linkId, ShowResultPage.class,
459                newParam);
460        return docLink;
461    }
462   
463        /**
464         * Add contentSearch form (FCS)
465         * @newParam solrDocument
466         */
467        private void addSearchServiceForm(final SolrDocument solrDocument) {
468                final WebMarkupContainer contentSearchContainer = new WebMarkupContainer("contentSearch");
469                add(contentSearchContainer);
470               
471                if (solrDocument.containsKey(FacetConstants.FIELD_SEARCH_SERVICE)) {
472                        try {
473                                // building map (CQL endpoint -> List with resource ID)
474                                HashMap<String, List<String>> aggregrationContextMap = new HashMap<String, List<String>>();
475                                List<String> idList = new ArrayList<String>();
476                                idList.add(solrDocument.getFirstValue(FacetConstants.FIELD_ID).toString());
477                                aggregrationContextMap.put(solrDocument.getFirstValue(FacetConstants.FIELD_SEARCH_SERVICE).toString(), idList);
478                                Label contentSearchLabel = new Label("contentSearchForm", HtmlFormCreator.getContentSearchForm(aggregrationContextMap, "Plain text search via Federated Content Search"));
479                                contentSearchLabel.setEscapeModelStrings(false);                               
480                                contentSearchContainer.add(contentSearchLabel);
481                        } catch (UnsupportedEncodingException uee) {
482                                contentSearchContainer.setVisible(false);
483                        }
484                } else {
485                        contentSearchContainer.setVisible(false);
486                }
487        }
488       
489        /**
490         * Add complete CMDI view
491         * @newParam solrDocument
492         */
493        private void addCompleteCmdiView(final SolrDocument solrDocument) {
494                StringWriter strWriter = new StringWriter();
495
496        final Processor proc = new Processor(false);
497        final XsltCompiler comp = proc.newXsltCompiler();
498
499        try {
500                final XsltExecutable exp = comp.compile(new StreamSource(xslFile.getFile()));
501                final XdmNode source = proc.newDocumentBuilder().build(
502                                new StreamSource(new InputStreamReader(new URL(solrDocument.getFirstValue(FacetConstants.FIELD_COMPLETE_METADATA).toString()).openStream())));
503                final Serializer out = new Serializer();
504                out.setOutputProperty(Serializer.Property.METHOD, "html");
505                out.setOutputProperty(Serializer.Property.INDENT, "yes");
506                out.setOutputProperty(Serializer.Property.ENCODING, "UTF-8");
507                out.setOutputWriter(strWriter);
508                final XsltTransformer trans = exp.load();
509
510                trans.setInitialContextNode(source);
511                trans.setDestination(out);
512                trans.transform();
513        } catch (Exception e) {
514                LOG.error("Couldn't create CMDI metadata: " + e.getMessage());
515                strWriter = new StringWriter().append("<b>Could not load complete CMDI metadata</b>");
516            }
517               
518        Label completeCmdiLabel = new Label("completeCmdi", strWriter.toString());
519                completeCmdiLabel.setEscapeModelStrings(false);
520                add(completeCmdiLabel);
521               
522                // remove complete CMDI view on page load
523                add(new Behavior() {
524                        private static final long serialVersionUID = 1865219352602175954L;
525
526                        public void renderHead(IHeaderResponse response) {
527                            response.render(JavaScriptHeaderItem.forScript("toogleDiv('completeCmdi', 'toogleLink')", null));
528                        }
529                });
530        }
531}
Note: See TracBrowser for help on using the repository browser.