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

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

Added feedbackFromUrl parameter.

File size: 17.3 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            addLandingPageLinks(solrDocument);
91            addResourceLinks(solrDocument);
92            addSearchServiceForm(solrDocument);
93            addCompleteCmdiView(solrDocument);
94           
95            add(new AjaxLazyLoadPanel("prevNextHeader") {
96
97                @Override
98                public Component getLazyLoadComponent(String markupId) {
99                    return new PrevNextHeaderPanel(markupId, docId, query);
100                }
101
102                @Override
103                public Component getLoadingComponent(String markupId) {
104                    return new PrevNextHeaderPanel(markupId);
105                }
106            });
107        } else {
108            setResponsePage(new ResultNotFoundPage(parameters));
109        }
110
111        // add feedback link
112        addFeedbackLink(parameters);
113    }
114
115    private String getHref(String linkToOriginalContext) {
116        String result = linkToOriginalContext;
117        if (linkToOriginalContext != null) {
118            if (linkToOriginalContext.startsWith(FacetConstants.TEST_HANDLE_MPI_PREFIX)) {
119                linkToOriginalContext = linkToOriginalContext.replace(FacetConstants.TEST_HANDLE_MPI_PREFIX, FacetConstants.HANDLE_MPI_PREFIX);
120            }
121            if (linkToOriginalContext.startsWith(FacetConstants.HANDLE_MPI_PREFIX)) {
122                result = VloConfig.getIMDIBrowserUrl(linkToOriginalContext);
123            } else {
124                try {
125                    new URL(linkToOriginalContext);
126                } catch (MalformedURLException e) {
127                    LOG.debug("Link to original context is incorrect:", e);
128                    result = null;
129                }
130            }
131        }
132        return result;
133    }
134
135        private void addAttributesTable(final SolrDocument solrDocument) {
136                solrDocument.remove(FacetConstants.FIELD_LANGUAGE);     // ignore language entry, because of FIELD_LANGUAGE_LINK
137        DocumentAttributesDataProvider attributeProvider = new DocumentAttributesDataProvider(solrDocument);
138        @SuppressWarnings("unchecked")
139                DataTable table = new DataTable("attributesTable", createAttributesColumns(), attributeProvider, 250);
140        table.setTableBodyCss("attributesTbody");
141        table.addTopToolbar(new HeadersToolbar(table, null));
142        add(table);
143    }
144
145    @SuppressWarnings({ "serial" })
146    private IColumn[] createAttributesColumns() {
147        IColumn[] columns = new IColumn[2];
148
149        columns[0] = new PropertyColumn<Object>(new ResourceModel(Resources.FIELD), "field") {
150
151            @Override
152            public String getCssClass() {
153                return "attribute";
154            }
155        };
156
157        columns[1] = new AbstractColumn<DocumentAttribute>(new ResourceModel(Resources.VALUE)) {
158            @Override
159            public void populateItem(Item<ICellPopulator<DocumentAttribute>> cellItem, String componentId, IModel<DocumentAttribute> rowModel) {
160                DocumentAttribute attribute = rowModel.getObject();
161
162                if (attribute.getField().equals(FacetConstants.FIELD_LANGUAGE)) {
163                    cellItem.add(new SmartLinkMultiLineLabel(componentId, attribute.getValue()) {
164
165                        @Override
166                        protected void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag) {
167                            CharSequence body = StringUtils.toMultiLineHtml(getDefaultModelObjectAsString());
168                            replaceComponentTagBody(markupStream, openTag, getSmartLink(body));
169                        }
170                    });
171                } else if(attribute.getField().equals(FacetConstants.FIELD_LANGUAGES)) {
172                    cellItem.add(new SmartLinkMultiLineLabel(componentId, attribute.getValue()) {
173
174                        @Override
175                        protected void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag) {
176                                setEscapeModelStrings(false);
177                            CharSequence body = getDefaultModelObjectAsString();
178                            replaceComponentTagBody(markupStream, openTag, body);
179                        }
180                    });
181                } else {
182                    cellItem.add(new SmartLinkMultiLineLabel(componentId, attribute.getValue()) {
183
184                        @Override
185                        protected void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag) {
186                            CharSequence body = StringUtils.toMultiLineHtml(getDefaultModelObjectAsString());
187                            replaceComponentTagBody(markupStream, openTag, getSmartLink(body));
188                        }
189                    });
190                }
191            }
192
193            @Override
194            public String getCssClass() {
195                return "attributeValue";
196            }
197        };
198
199        return columns;
200    }
201   
202    /**
203     * Add links to landing pages to the results shown.<br><br>
204     *
205     * Depending on the number of links to be shown, at most one of the labels
206     * in the accompanying HTML page that is subject to Wicket is made
207     * visible.<br><br>
208     *
209     * @param solrDocument the document to add the landing page links to
210     */
211    @SuppressWarnings("serial")
212    private void addLandingPageLinks(SolrDocument solrDocument) {
213
214        // add the labels defined in the HTML page
215        Label oneLandingPageText;
216        oneLandingPageText = new Label("oneLandingPage", 
217                new ResourceModel(Resources.LANDING_PAGE).getObject() + ":");
218        this.add(oneLandingPageText);
219
220        Label moreLandingPagesText;
221        moreLandingPagesText = new Label("moreLandingPages", 
222                new ResourceModel(Resources.LANDING_PAGES).getObject() + ":");
223        this.add(moreLandingPagesText);
224
225        // also, add the list of links
226        RepeatingView repeatingView = new RepeatingView("landingPageList");
227        add(repeatingView);
228
229        if (!solrDocument.containsKey(FacetConstants.FIELD_LANDINGPAGE)) {
230           
231            /* Since there are no links to be shown, make both labels defined in
232             * the page invisible
233             */
234            oneLandingPageText.setVisible(false);
235            moreLandingPagesText.setVisible(false);
236        } else {
237            //  make one of the two labels invisible
238
239            Collection<Object> landingPages = 
240                    solrDocument.getFieldValues(FacetConstants.FIELD_LANDINGPAGE);
241            if (landingPages.size() > 1) {
242               
243                // the list will contain more than one landing page link
244                oneLandingPageText.setVisible(false);
245                moreLandingPagesText.setVisible(true);
246            } else {
247                // the list will contain exactly one landing page link.
248                oneLandingPageText.setVisible(true);
249                moreLandingPagesText.setVisible(false);
250            }
251           
252            // generate the list of links
253            for (Iterator<Object> it = landingPages.iterator(); it.hasNext();) {
254                final Object landingPage;
255                landingPage = it.next();
256
257                // keeloo: describe this
258                repeatingView.add(
259                        new AjaxLazyLoadPanel(repeatingView.newChildId()) {
260                            @Override
261                            public Component getLazyLoadComponent(String markupId) {
262                                String landingPageLink;
263                                landingPageLink = landingPage.toString();
264                               
265                                // create a landing page link panel
266                                return new LandingPageLinkPanel(markupId,
267                                        landingPage.toString());
268                            }
269                        });
270            }
271        }
272    }
273
274    @SuppressWarnings("serial")
275    private void addResourceLinks(SolrDocument solrDocument) {
276        RepeatingView repeatingView = new RepeatingView("resourceList");
277        add(repeatingView);
278        if (solrDocument.containsKey(FacetConstants.FIELD_RESOURCE)) {
279            Collection<Object> resources = solrDocument.getFieldValues(FacetConstants.FIELD_RESOURCE);
280            for (Object resource : resources) {
281                String[] split = resource.toString().split(Pattern.quote(FacetConstants.FIELD_RESOURCE_SPLIT_CHAR), 2);
282                final String mimeType = split[0];
283                final String resourceLink = split[1];
284                repeatingView.add(new AjaxLazyLoadPanel(repeatingView.newChildId()) {
285
286                    @Override
287                    public Component getLazyLoadComponent(String markupId) {
288                        return new ResourceLinkPanel(markupId, mimeType, resourceLink);
289                    }
290                });
291            }
292        } else {
293            repeatingView.add(new Label(repeatingView.newChildId(), new ResourceModel(Resources.NO_RESOURCE_FOUND)));
294        }
295    }
296   
297    private void addFeedbackLink(final PageParameters parameters) {
298        String thisURL = RequestUtils.toAbsolutePath(RequestCycle.get().urlFor(ShowResultPage.class, parameters).toString());
299        try {
300            thisURL = URLEncoder.encode(thisURL,"UTF-8");
301        } catch (UnsupportedEncodingException e) {
302            LOG.error(e.toString());
303        }
304       
305        Image resourceImg = new Image("feedbackImage", FEEDBACK_IMAGE.getResource());
306        String title = "Report an error";
307        resourceImg.add(new SimpleAttributeModifier("title", title));
308        resourceImg.add(new SimpleAttributeModifier("alt", title));
309        String href = getHref(feedbackfromURL+thisURL);
310        String name = feedbackfromURL+thisURL;
311        ExternalLink link = new ExternalLink("feedbackLink", href);
312        link.add(resourceImg);
313        add(new Label("feedbackLabel", "Found an error?"));
314        add(link);
315    }
316
317    public static BookmarkablePageLink<ShowResultPage> createBookMarkableLink(String linkId, SearchPageQuery query, String docId) {
318        PageParameters pageParameters = query.getPageParameters();
319        pageParameters.put(ShowResultPage.PARAM_DOC_ID, WicketURLEncoder.QUERY_INSTANCE.encode(docId));
320        BookmarkablePageLink<ShowResultPage> docLink = new BookmarkablePageLink<ShowResultPage>(linkId, ShowResultPage.class,
321                pageParameters);
322        return docLink;
323    }
324   
325        /**
326         * Add contentSearch form (FCS)
327         * @param solrDocument
328         */
329        private void addSearchServiceForm(final SolrDocument solrDocument) {
330                final WebMarkupContainer contentSearchContainer = new WebMarkupContainer("contentSearch");
331                add(contentSearchContainer);
332               
333                if (solrDocument.containsKey(FacetConstants.FIELD_SEARCH_SERVICE)) {
334                        try {
335                                // building map (CQL endpoint -> List with resource ID)
336                                HashMap<String, List<String>> aggregrationContextMap = new HashMap<String, List<String>>();
337                                List<String> idList = new ArrayList<String>();
338                                idList.add(solrDocument.getFirstValue(FacetConstants.FIELD_ID).toString());
339                                aggregrationContextMap.put(solrDocument.getFirstValue(FacetConstants.FIELD_SEARCH_SERVICE).toString(), idList);
340                                Label contentSearchLabel = new Label("contentSearchForm", HtmlFormCreator.getContentSearchForm(aggregrationContextMap));
341                                contentSearchLabel.setEscapeModelStrings(false);                               
342                                contentSearchContainer.add(contentSearchLabel);
343                        } catch (UnsupportedEncodingException uee) {
344                                contentSearchContainer.setVisible(false);
345                        }
346                } else {
347                        contentSearchContainer.setVisible(false);
348                }
349        }
350       
351        /**
352         * Add complete CMDI view
353         * @param solrDocument
354         */
355        private void addCompleteCmdiView(final SolrDocument solrDocument) {
356                StringWriter strWriter = new StringWriter();
357
358        final Processor proc = new Processor(false);
359        final XsltCompiler comp = proc.newXsltCompiler();
360
361        try {
362                final XsltExecutable exp = comp.compile(new StreamSource(xslFile.getFile()));
363                final XdmNode source = proc.newDocumentBuilder().build(
364                                new StreamSource(new InputStreamReader(new URL(solrDocument.getFirstValue(FacetConstants.FIELD_COMPLETE_METADATA).toString()).openStream())));
365                final Serializer out = new Serializer();
366                out.setOutputProperty(Serializer.Property.METHOD, "html");
367                out.setOutputProperty(Serializer.Property.INDENT, "yes");
368                out.setOutputWriter(strWriter);
369                final XsltTransformer trans = exp.load();
370
371                trans.setInitialContextNode(source);
372                trans.setDestination(out);
373                trans.transform();
374        } catch (Exception e) {
375                LOG.error("Couldn't create CMDI metadata: "+e.getMessage());
376                strWriter = new StringWriter().append("<b>Could not load complete CMDI metadata</b>");
377        }               
378               
379        Label completeCmdiLabel = new Label("completeCmdi", strWriter.toString());
380                completeCmdiLabel.setEscapeModelStrings(false);
381                add(completeCmdiLabel);
382               
383                // remove complete CMDI view on page load
384                add(new AbstractBehavior() {
385                        private static final long serialVersionUID = 1865219352602175954L;
386
387                        @Override
388                        public void renderHead(IHeaderResponse response) {
389                                super.renderHead(response);
390                                response.renderOnLoadJavascript("toogleDiv('completeCmdi', 'toogleLink')");
391                        }
392                });
393        }
394}
Note: See TracBrowser for help on using the repository browser.