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

Last change on this file since 4199 was 4199, checked in by keeloo, 10 years ago
File size: 22.5 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.VloSession;
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.request.mapper.parameter.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.slf4j.Logger;
57import org.slf4j.LoggerFactory;
58
59/**
60 * Page showing VLO search results
61 *
62 * @author keeloo, for the addLandingPage links method and annotations
63 */
64public class ShowResultPage extends BasePage {
65
66    private final static Logger LOG = LoggerFactory.getLogger(ShowResultPage.class);
67    public static final String PARAM_DOC_ID = "docId";
68    public static final String feedbackfromURL = VloConfig.getFeedbackFromUrl();
69   
70    private final URL xslFile = getClass().getResource("/cmdi2xhtml.xsl");
71   
72    @SuppressWarnings("serial")
73    public ShowResultPage(final PageParameters currentParam) {
74       
75        super(currentParam);
76        final String docId = WicketURLDecoder.QUERY_INSTANCE.decode(getPageParameters().getString(PARAM_DOC_ID, null));
77        SolrDocument solrDocument = DaoLocator.getSearchResultsDao().getSolrDocument(docId);
78        if (solrDocument != null) {
79            final SearchPageQuery query = new SearchPageQuery(currentParam);
80           
81            // now the persistent parameters are not in the query parameters
82            PageParameters newParam = new PageParameters ();
83            // add the new query parameters to this map
84            newParam.putAll(query.getPageParameters());
85            // add the persistent parameters to this map
86            //newParam = webApp.reflectPersistentParameters(newParam);
87           
88            newParam = ((VloWebApplication.ThemedSession)getSession()).reflectPersistentParameters(newParam);
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     * @param
183     */
184    private IColumn[] createAttributesColumns() {
185        IColumn[] columns = new IColumn[2];
186
187        // create the column for the attribute names
188        columns[0] = new PropertyColumn<Object>(new ResourceModel(Resources.FIELD), "field") {
189
190            @Override
191            public String getCssClass() {
192                return "attribute";
193            }
194        };
195
196        // create the column for the values of the attributes
197        columns[1] = new AbstractColumn<DocumentAttribute>(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                        protected 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                        protected 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                        protected 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
248        return columns;
249    }
250   
251    /**
252     * Add landing page links to the result page.
253     *
254     * @param solrDocument the document to get the links from
255     */
256    private void addLandingPageLinks(SolrDocument solrDocument) {
257       
258        Label oneLandingPageText;
259        oneLandingPageText = new Label("oneLandingPage",
260                new ResourceModel(Resources.LANDING_PAGE).getObject() + ":");
261        this.add(oneLandingPageText);
262
263        Label moreLandingPagesText;
264        moreLandingPagesText = new Label("moreLandingPages",
265                new ResourceModel(Resources.LANDING_PAGES).getObject() + ":");
266        this.add(moreLandingPagesText);
267
268        RepeatingView repeatingView = new RepeatingView("landingPageList");
269        add(repeatingView);
270
271        /*
272         * Depending on the number of links to be shown, at most one of the
273         * labels in the accompanying HTML page that is subject to Wicket is
274         * made visible.
275         */
276        if (!solrDocument.containsKey(FacetConstants.FIELD_LANDINGPAGE)) {
277           
278            /* Since there are no links to be shown, make both labels defined in
279             * the page invisible
280             */
281            oneLandingPageText.setVisible(false);
282            moreLandingPagesText.setVisible(false);
283        } else {
284            //  make one of the two labels invisible
285
286            Collection<Object> landingPages = 
287                    solrDocument.getFieldValues(FacetConstants.FIELD_LANDINGPAGE);
288            if (landingPages.size() > 1) {
289               
290                // the list will contain more than one landing page link
291                oneLandingPageText.setVisible(false);
292                moreLandingPagesText.setVisible(true);
293            } else {
294                // the list will contain exactly one landing page link.
295                oneLandingPageText.setVisible(true);
296                moreLandingPagesText.setVisible(false);
297            }
298           
299            // generate the list of links
300            for (Iterator<Object> it = landingPages.iterator(); it.hasNext();) {
301                final Object landingPage;
302                landingPage = it.next();
303
304                // add a link to the list
305                repeatingView.add(
306                        new AjaxLazyLoadPanel(repeatingView.newChildId()) {
307                            @Override
308                            public Component getLazyLoadComponent(String markupId) {
309                                String landingPageLink;
310                                landingPageLink = landingPage.toString();
311
312                                // create a panel for the link
313                                return new LandingPageLinkPanel(markupId,
314                                        landingPage.toString());
315                            }
316                        });
317            }
318        }
319    }
320   
321    /**
322     * Add search page links to the result page.
323     *
324     * @param solrDocument the document to get the links from
325     */
326    private void addSearchPageLinks(SolrDocument solrDocument) {
327       
328        Label oneSearchPageText;
329        oneSearchPageText = new Label("oneSearchPage",
330                new ResourceModel(Resources.SEARCH_PAGE).getObject() + ":");
331        this.add(oneSearchPageText);
332
333        Label moreSearchPagesText;
334        moreSearchPagesText = new Label("moreSearchPages",
335                new ResourceModel(Resources.SEARCH_PAGES).getObject() + ":");
336        this.add(moreSearchPagesText);
337
338        RepeatingView repeatingView = new RepeatingView("searchPageList");
339        add(repeatingView);
340
341        /*
342         * Depending on the number of links to be shown, at most one of the
343         * labels in the accompanying HTML page that is subject to Wicket is
344         * made visible.
345         */
346        if (!solrDocument.containsKey(FacetConstants.FIELD_SEARCHPAGE)) {
347           
348            /* Since there are no links to be shown, make both labels defined in
349             * the page invisible
350             */
351            oneSearchPageText.setVisible(false);
352            moreSearchPagesText.setVisible(false);
353        } else {
354            //  make one of the two labels invisible
355
356            Collection<Object> searchPages = 
357                    solrDocument.getFieldValues(FacetConstants.FIELD_SEARCHPAGE);
358            if (searchPages.size() > 1) {
359               
360                // the list will contain more than one landing page link
361                oneSearchPageText.setVisible(false);
362                moreSearchPagesText.setVisible(true);
363            } else {
364                // the list will contain exactly one landing page link.
365                oneSearchPageText.setVisible(true);
366                moreSearchPagesText.setVisible(false);
367            }
368           
369            // generate the list of links
370            for (Iterator<Object> it = searchPages.iterator(); it.hasNext();) {
371                final Object searchPage;
372                searchPage = it.next();
373
374                // add a link to the list
375                repeatingView.add(
376                        new AjaxLazyLoadPanel(repeatingView.newChildId()) {
377                            @Override
378                            public Component getLazyLoadComponent(String markupId) {
379                                String searchPageLink;
380                                searchPageLink = searchPage.toString();
381
382                                // create a panel for the link
383                                return new SearchPageLinkPanel(markupId,
384                                        searchPage.toString());
385                            }
386                        });
387            }
388        }
389    }
390
391    /**
392     * Add links to resources other than search or landing pages to the result
393     * page.
394     *
395     * @param solrDocument the document to get the links from
396     */
397    private void addResourceLinks(SolrDocument solrDocument) {
398        RepeatingView repeatingView = new RepeatingView("resourceList");
399        add(repeatingView);
400        if (solrDocument.containsKey(FacetConstants.FIELD_RESOURCE)) {     
401            Collection<Object> resources = solrDocument.getFieldValues(FacetConstants.FIELD_RESOURCE);
402            if (resources.size() > 1) {
403                repeatingView.add(new Label(repeatingView.newChildId(), new ResourceModel(Resources.RESOURCE_PL)));
404            } else {
405                repeatingView.add(new Label(repeatingView.newChildId(), new ResourceModel(Resources.RESOURCE)));
406            }
407            for (Object resource : resources) {
408                String[] split = resource.toString().split(Pattern.quote(FacetConstants.FIELD_RESOURCE_SPLIT_CHAR), 2);
409                final String mimeType = split[0];
410                final String resourceLink = split[1];
411                repeatingView.add(new AjaxLazyLoadPanel(repeatingView.newChildId()) {
412
413                    @Override
414                    public Component getLazyLoadComponent(String markupId) {
415                        return new ResourceLinkPanel(markupId, mimeType, resourceLink);
416                    }
417                });
418            }
419        } else {
420            repeatingView.add(new Label(repeatingView.newChildId(), new ResourceModel(Resources.NO_RESOURCE_FOUND)));
421        }
422    }
423   
424    private void addFeedbackLink(final PageParameters parameters) {
425        String thisURL = RequestUtils.toAbsolutePath(RequestCycle.get().urlFor(ShowResultPage.class, parameters).toString());
426        try {
427            thisURL = URLEncoder.encode(thisURL,"UTF-8");
428        } catch (UnsupportedEncodingException e) {
429            LOG.error(e.toString());
430        }
431       
432        // Image resourceImg = new Image("feedbackImage", FEEDBACK_IMAGE.getResource());
433        // String title = "Report an error";
434        // resourceImg.add(new SimpleAttributeModifier("title", title));
435        // resourceImg.add(new SimpleAttributeModifier("alt", title));
436        String href = getHref(feedbackfromURL+thisURL);
437        String name = feedbackfromURL+thisURL;
438        ExternalLink link = new ExternalLink("feedbackLink", href, "found an error?");
439        // link.add(resourceImg);
440        // add(new Label("feedbackLabel", "Found an error?"));
441        add(link);
442    }
443
444    public static BookmarkablePageLink<ShowResultPage> createBookMarkableLink(String linkId, SearchPageQuery query, String docId, VloSession session) {
445        PageParameters pageParameters = query.getPageParameters();
446        pageParameters.put(ShowResultPage.PARAM_DOC_ID, WicketURLEncoder.QUERY_INSTANCE.encode(docId));
447       
448        // webApp.reflectPersistentParameters(pageParameters);
449        // instead of this: pass page parameters back to the session
450        session.reflectPersistentParameters(pageParameters);
451
452        BookmarkablePageLink<ShowResultPage> docLink = new BookmarkablePageLink<ShowResultPage>(linkId, ShowResultPage.class,
453                pageParameters);
454        return docLink;
455    }
456   
457        /**
458         * Add contentSearch form (FCS)
459         * @param solrDocument
460         */
461        private void addSearchServiceForm(final SolrDocument solrDocument) {
462                final WebMarkupContainer contentSearchContainer = new WebMarkupContainer("contentSearch");
463                add(contentSearchContainer);
464               
465                if (solrDocument.containsKey(FacetConstants.FIELD_SEARCH_SERVICE)) {
466                        try {
467                                // building map (CQL endpoint -> List with resource ID)
468                                HashMap<String, List<String>> aggregrationContextMap = new HashMap<String, List<String>>();
469                                List<String> idList = new ArrayList<String>();
470                                idList.add(solrDocument.getFirstValue(FacetConstants.FIELD_ID).toString());
471                                aggregrationContextMap.put(solrDocument.getFirstValue(FacetConstants.FIELD_SEARCH_SERVICE).toString(), idList);
472                                Label contentSearchLabel = new Label("contentSearchForm", HtmlFormCreator.getContentSearchForm(aggregrationContextMap, "Plain text search via Federated Content Search"));
473                                contentSearchLabel.setEscapeModelStrings(false);                               
474                                contentSearchContainer.add(contentSearchLabel);
475                        } catch (UnsupportedEncodingException uee) {
476                                contentSearchContainer.setVisible(false);
477                        }
478                } else {
479                        contentSearchContainer.setVisible(false);
480                }
481        }
482       
483        /**
484         * Add complete CMDI view
485         * @param solrDocument
486         */
487        private void addCompleteCmdiView(final SolrDocument solrDocument) {
488                StringWriter strWriter = new StringWriter();
489
490        final Processor proc = new Processor(false);
491        final XsltCompiler comp = proc.newXsltCompiler();
492
493        try {
494                final XsltExecutable exp = comp.compile(new StreamSource(xslFile.getFile()));
495                final XdmNode source = proc.newDocumentBuilder().build(
496                                new StreamSource(new InputStreamReader(new URL(solrDocument.getFirstValue(FacetConstants.FIELD_COMPLETE_METADATA).toString()).openStream())));
497                final Serializer out = new Serializer();
498                out.setOutputProperty(Serializer.Property.METHOD, "html");
499                out.setOutputProperty(Serializer.Property.INDENT, "yes");
500                out.setOutputProperty(Serializer.Property.ENCODING, "UTF-8");
501                out.setOutputWriter(strWriter);
502                final XsltTransformer trans = exp.load();
503
504                trans.setInitialContextNode(source);
505                trans.setDestination(out);
506                trans.transform();
507        } catch (Exception e) {
508                LOG.error("Couldn't create CMDI metadata: " + e.getMessage());
509                strWriter = new StringWriter().append("<b>Could not load complete CMDI metadata</b>");
510            }
511               
512        Label completeCmdiLabel = new Label("completeCmdi", strWriter.toString());
513                completeCmdiLabel.setEscapeModelStrings(false);
514                add(completeCmdiLabel);
515               
516                // remove complete CMDI view on page load
517                add(new AbstractBehavior() {
518                        private static final long serialVersionUID = 1865219352602175954L;
519
520                        @Override
521                        public void renderHead(IHeaderResponse response) {
522                                super.renderHead(response);
523                                response.renderOnLoadJavascript("toogleDiv('completeCmdi', 'toogleLink')");
524                        }
525                });
526        }
527}
Note: See TracBrowser for help on using the repository browser.