org.onexus.website.api.widgets.download.DownloadWidget.java Source code

Java tutorial

Introduction

Here is the source code for org.onexus.website.api.widgets.download.DownloadWidget.java

Source

/**
 *  Copyright 2012 Universitat Pompeu Fabra.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *
 */
package org.onexus.website.api.widgets.download;

import org.apache.wicket.AttributeModifier;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.event.IEvent;
import org.apache.wicket.markup.head.CssHeaderItem;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.request.resource.AbstractResource;
import org.apache.wicket.request.resource.ContentDisposition;
import org.apache.wicket.request.resource.CssResourceReference;
import org.apache.wicket.request.resource.IResource;
import org.apache.wicket.request.resource.JavaScriptResourceReference;
import org.apache.wicket.request.resource.ResourceReference;
import org.onexus.collection.api.ICollectionManager;
import org.onexus.collection.api.IEntityTable;
import org.onexus.collection.api.query.Query;
import org.onexus.website.api.WebsiteApplication;
import org.onexus.website.api.events.EventQueryUpdate;
import org.onexus.website.api.pages.browser.BrowserPageStatus;
import org.onexus.website.api.widgets.Widget;
import org.onexus.website.api.widgets.download.formats.ExcelFormat;
import org.onexus.website.api.widgets.download.formats.IDownloadFormat;
import org.onexus.website.api.widgets.download.formats.TsvFormat;
import org.onexus.website.api.widgets.download.scripts.BashScript;
import org.onexus.website.api.widgets.download.scripts.IQueryScript;
import org.onexus.website.api.widgets.download.scripts.PerlScript;
import org.onexus.website.api.widgets.download.scripts.Python2Script;
import org.onexus.website.api.widgets.download.scripts.Python3Script;
import org.onexus.website.api.widgets.download.scripts.RScript;

import javax.inject.Inject;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

public class DownloadWidget extends Widget<DownloadWidgetConfig, DownloadWidgetStatus> {

    public static final ResourceReference CSS = new CssResourceReference(DownloadWidget.class,
            "prettify/prettify.css");
    public static final ResourceReference JS = new JavaScriptResourceReference(DownloadWidget.class,
            "prettify/prettify.js");
    private static final Pattern COMMA_PATTERN = Pattern.compile(",");

    @Inject
    private ICollectionManager collectionManager;

    public static final Map<String, IQueryScript> SCRIPTS_MAP = new LinkedHashMap<String, IQueryScript>();

    static {
        addScript(new RScript());
        addScript(new Python2Script());
        addScript(new Python3Script());
        addScript(new PerlScript());
        addScript(new BashScript());
    }

    private static void addScript(IQueryScript queryScript) {
        SCRIPTS_MAP.put(queryScript.getLabel().toLowerCase(), queryScript);
    }

    private static final Map<String, IDownloadFormat> FORMATS_MAP = new LinkedHashMap<String, IDownloadFormat>();

    static {
        addFormat(new TsvFormat());
        addFormat(new ExcelFormat());
    }

    private static void addFormat(IDownloadFormat format) {
        FORMATS_MAP.put(format.getLabel().toLowerCase(), format);
    }

    private String webserviceUrl;
    private IDownloadFormat format;

    public DownloadWidget(String componentId, IModel<DownloadWidgetStatus> statusModel) {
        super(componentId, statusModel);
        onEventFireUpdate(EventQueryUpdate.class);

        // Get query
        final StringBuilder oql = new StringBuilder();
        Query query = getQuery();
        query.toString(oql, true);

        // Webservice URL
        String serviceMount = collectionManager.getMount();
        webserviceUrl = WebsiteApplication.toAbsolutePath('/' + serviceMount);

        // Download form
        final Form<String> downloadForm = new Form<String>("form");
        downloadForm.setOutputMarkupId(true);

        List<IDownloadFormat> formats = getFormats();
        if (formats.isEmpty()) {
            throw new UnsupportedOperationException("Download widget: At least one format is needed.");
        }
        setFormat(formats.get(0));
        downloadForm.add(new DropDownChoice<IDownloadFormat>("format",
                new PropertyModel<IDownloadFormat>(this, "format"), formats));
        add(downloadForm);

        final AjaxDownloadBehavior ajaxDownloadBehavior = new AjaxDownloadBehavior() {
            @Override
            protected String getFileName() {
                return DownloadWidget.this.getFileName();
            }

            @Override
            protected IResource getResource() {
                return new DownloadResource();
            }
        };
        downloadForm.add(ajaxDownloadBehavior);

        AjaxButton link = new AjaxButton("download") {

            @Override
            protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
                ajaxDownloadBehavior.initiate(target);
                target.add(form);
            }
        };
        downloadForm.add(link);

        List<IQueryScript> scripts = getScripts();
        // Add scripts
        ListView scriptsView = new ListView<IQueryScript>("scripts", scripts) {
            @Override
            protected void populateItem(ListItem<IQueryScript> item) {

                IQueryScript script = item.getModelObject();

                // Code body
                WebMarkupContainer body = new WebMarkupContainer("body");
                body.setMarkupId(item.getMarkupId() + "-body");
                item.add(body);
                body.add(new Label("code", script.getContent(oql.toString(), webserviceUrl))
                        .setEscapeModelStrings(false));

                // Code toggle
                Label toggle = new Label("toggle", "Use in " + script.getLabel() + " script");
                toggle.add(new AttributeModifier("href", "#" + body.getMarkupId()));
                item.add(toggle);

            }
        };

        if (scripts.isEmpty()) {
            scriptsView.setVisible(false);
        }
        add(scriptsView);

    }

    private String getFileName() {
        BrowserPageStatus status = DownloadWidget.this.findParentStatus(BrowserPageStatus.class);

        if (status == null) {
            return getFormat().getFileName("datafile");
        }

        return getFormat().getFileName(status.getCurrentTabId());
    }

    private List<IDownloadFormat> getFormats() {
        List<IDownloadFormat> formats = new ArrayList<IDownloadFormat>();

        String formatsStr = getConfig().getFormats();

        if (formatsStr == null) {
            formats.addAll(FORMATS_MAP.values());
        } else {
            String[] values = COMMA_PATTERN.split(formatsStr);
            for (String value : values) {
                IDownloadFormat format = FORMATS_MAP.get(value.trim().toLowerCase());
                if (format != null) {
                    formats.add(format);
                }
            }
        }

        return formats;
    }

    private List<IQueryScript> getScripts() {
        List<IQueryScript> scripts = new ArrayList<IQueryScript>();

        String scriptsStr = getConfig().getScripts();

        if (scriptsStr == null) {
            scripts.addAll(SCRIPTS_MAP.values());
        } else {
            String[] values = COMMA_PATTERN.split(scriptsStr);
            for (String value : values) {
                IQueryScript script = SCRIPTS_MAP.get(value.trim().toLowerCase());
                if (script != null) {
                    scripts.add(script);
                }
            }
        }

        return scripts;
    }

    @Override
    public void onEvent(IEvent<?> event) {

        if (event.getPayload() instanceof AjaxRequestTarget) {
            AjaxRequestTarget target = (AjaxRequestTarget) event.getPayload();
            target.appendJavaScript("prettyPrint();");
        }

    }

    @Override
    public void renderHead(IHeaderResponse response) {
        response.render(CssHeaderItem.forReference(CSS));
        response.render(JavaScriptHeaderItem.forReference(JS));
    }

    public IDownloadFormat getFormat() {
        return format;
    }

    public void setFormat(IDownloadFormat format) {
        this.format = format;
    }

    private ICollectionManager getCollectionManager() {

        if (collectionManager == null) {
            WebsiteApplication.inject(this);
        }

        return collectionManager;
    }

    private class DownloadResource extends AbstractResource {

        @Override
        protected ResourceResponse newResourceResponse(Attributes attributes) {

            ResourceResponse resourceResponse = new ResourceResponse();

            resourceResponse.setContentDisposition(ContentDisposition.ATTACHMENT);
            resourceResponse.setContentType(getFormat().getContentType());
            resourceResponse.setFileName(getFileName());
            resourceResponse.setWriteCallback(new WriteCallback() {
                @Override
                public void writeData(Attributes attributes) throws IOException {

                    Query query = getQuery();
                    IDownloadFormat format = getFormat();

                    if (format.getMaxRowsLimit() != null
                            && (query.getCount() == null || format.getMaxRowsLimit() < query.getCount())) {
                        query.setCount(format.getMaxRowsLimit());
                    }

                    IEntityTable table = getCollectionManager().load(query);
                    OutputStream out = attributes.getResponse().getOutputStream();
                    getFormat().write(table, out);
                }
            });

            return resourceResponse;
        }
    }

}