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

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

Added support for search page type of resources.

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