eu.esdihumboldt.hale.server.webtransform.war.pages.UploadAndTransForm.java Source code

Java tutorial

Introduction

Here is the source code for eu.esdihumboldt.hale.server.webtransform.war.pages.UploadAndTransForm.java

Source

/*
 * Copyright (c) 2012 Data Harmonisation Panel
 * 
 * All rights reserved. This program and the accompanying materials are made
 * available under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution. If not, see <http://www.gnu.org/licenses/>.
 * 
 * Contributors:
 *     Data Harmonisation Panel <http://www.dhpanel.eu>
 */

package eu.esdihumboldt.hale.server.webtransform.war.pages;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

import javax.annotation.Nullable;

import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.extensions.markup.html.form.select.IOptionRenderer;
import org.apache.wicket.extensions.markup.html.form.select.Select;
import org.apache.wicket.extensions.markup.html.form.select.SelectOptions;
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.form.IChoiceRenderer;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.form.upload.FileUpload;
import org.apache.wicket.markup.html.form.upload.FileUploadField;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.apache.wicket.validation.IValidatable;
import org.apache.wicket.validation.IValidator;
import org.apache.wicket.validation.ValidationError;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.content.IContentType;

import com.google.common.base.Function;
import com.google.common.collect.Lists;

import de.fhg.igd.slf4jplus.ALogger;
import de.fhg.igd.slf4jplus.ALoggerFactory;
import eu.esdihumboldt.hale.common.core.io.ExportProvider;
import eu.esdihumboldt.hale.common.core.io.HaleIO;
import eu.esdihumboldt.hale.common.core.io.IOProvider;
import eu.esdihumboldt.hale.common.core.io.Value;
import eu.esdihumboldt.hale.common.core.io.extension.IOProviderDescriptor;
import eu.esdihumboldt.hale.common.core.io.project.model.IOConfiguration;
import eu.esdihumboldt.hale.common.core.io.supplier.FileIOSupplier;
import eu.esdihumboldt.hale.common.core.io.supplier.LocatableInputSupplier;
import eu.esdihumboldt.hale.common.headless.EnvironmentService;
import eu.esdihumboldt.hale.common.headless.HeadlessIO;
import eu.esdihumboldt.hale.common.headless.TransformationEnvironment;
import eu.esdihumboldt.hale.common.headless.transform.TransformationWorkspace;
import eu.esdihumboldt.hale.common.instance.io.InstanceReader;
import eu.esdihumboldt.hale.common.instance.io.InstanceWriter;

/**
 * Form for uploading and transforming data.
 * 
 * @author Simon Templer
 */
public class UploadAndTransForm extends Form<Void> {

    /**
     * Model for a parameter field.
     */
    private class FieldFieldModel implements IModel<String> {

        private static final long serialVersionUID = 7866817725347689084L;

        private final String param;

        /**
         * Create a model for a parameter field.
         * 
         * @param param the parameter name
         */
        public FieldFieldModel(String param) {
            this.param = param;
        }

        @Override
        public void detach() {
            // nuthin'
        }

        @Override
        public String getObject() {
            Value value = getTarget().getProviderConfiguration().get(param);
            if (value != null) {
                return value.as(String.class);
            }

            return null;
        }

        @Override
        public void setObject(String object) {
            getTarget().getProviderConfiguration().put(param, Value.of(object));
        }

    }

    /**
     * Choice renderer for content type IDs.
     */
    private static class ContentTypeChoiceRenderer implements IChoiceRenderer<String> {

        private static final long serialVersionUID = -6542046435287452517L;

        @Override
        public Object getDisplayValue(String object) {
            return Platform.getContentTypeManager().getContentType(object).getName();
        }

        @Override
        public String getIdValue(String object, int index) {
            return object;
        }

    }

    private static final long serialVersionUID = 8904573677189598470L;

    private static final ALogger log = ALoggerFactory.getLogger(UploadAndTransForm.class);

    @SpringBean
    private EnvironmentService environmentService;

    private final String projectId;

    private final FileUploadField file;

    private IOConfiguration target;

    private static final IOptionRenderer<NamedIOConfiguration> RENDERER = new IOptionRenderer<NamedIOConfiguration>() {

        private static final long serialVersionUID = 4714894437575668850L;

        @Override
        public String getDisplayValue(NamedIOConfiguration object) {
            String name = object.getName();
            if (name != null && !name.isEmpty()) {
                return name;
            }
            return object.getConfig().getProviderId();
        }

        @Override
        public IModel<NamedIOConfiguration> getModel(NamedIOConfiguration value) {
            return new Model<NamedIOConfiguration>(value);
        }
    };

    /**
     * Create a form for uploading and transforming data.
     * 
     * @param id the component ID
     * @param projectId the project ID
     */
    public UploadAndTransForm(String id, String projectId) {
        super(id);
        this.projectId = projectId;

        // multi-part always needed for uploads
        setMultiPart(true);

        add(new FeedbackPanel("feedback"));

        // Add file input field
        add(file = new FileUploadField("upload"));
        file.add(new IValidator<List<FileUpload>>() {

            private static final long serialVersionUID = -5668788086384105101L;

            @Override
            public void validate(IValidatable<List<FileUpload>> validatable) {
                if (validatable.getValue().isEmpty()) {
                    validatable.error(new ValidationError("No source files specified."));
                }
            }

        });

        // target selection
        Select<IOConfiguration> selectTarget = new Select<IOConfiguration>("target",
                new PropertyModel<IOConfiguration>(this, "target"));
        add(selectTarget);

        TransformationEnvironment env = environmentService.getEnvironment(projectId);

        // determine presets
        Collection<NamedIOConfiguration> presetList = new ArrayList<>();
        for (Entry<String, ? extends IOConfiguration> entry : env.getExportPresets().entrySet()) {
            presetList.add(new NamedIOConfiguration(entry.getKey(), entry.getValue()));
        }
        SelectOptions<NamedIOConfiguration> presets = new SelectOptions<NamedIOConfiguration>("presets", presetList,
                RENDERER);
        selectTarget.add(presets);

        // determine valid exporters
        Collection<NamedIOConfiguration> templateList = new ArrayList<>();
        for (Entry<String, ? extends IOConfiguration> entry : env.getExportTemplates().entrySet()) {
            presetList.add(new NamedIOConfiguration(entry.getKey(), entry.getValue()));
        }
        SelectOptions<NamedIOConfiguration> exporters = new SelectOptions<NamedIOConfiguration>("exporters",
                templateList, RENDERER);
        selectTarget.add(exporters);

        // initial selection
        if (!presetList.isEmpty()) {
            setTarget(presetList.iterator().next().getConfig());
        } else if (!templateList.isEmpty()) {
            setTarget(templateList.iterator().next().getConfig());
        }

        // panel for I/O configuration
        final WebMarkupContainer config = new WebMarkupContainer("config");
        config.setOutputMarkupId(true);
        add(config);

        IModel<List<String>> parameterModel = new LoadableDetachableModel<List<String>>() {

            private static final long serialVersionUID = 1018038661733512580L;

            @Override
            protected List<String> load() {
                Set<String> properties = new LinkedHashSet<String>();

                if (target != null && target.getProviderId() != null) {
                    // must have
                    properties.add(IOProvider.PARAM_CONTENT_TYPE);

                    // what is supported

                    IOProvider p = HeadlessIO.loadProvider(target);
                    properties.addAll(p.getSupportedParameters());

                    // not allowed
                    properties.remove(ExportProvider.PARAM_TARGET);
                }

                return new ArrayList<String>(properties);
            }
        };

        ListView<String> parameterView = new ListView<String>("param", parameterModel) {

            private static final long serialVersionUID = -7838477347365823022L;

            @Override
            protected void populateItem(ListItem<String> item) {
                boolean isContentType = IOProvider.PARAM_CONTENT_TYPE.equals(item.getModelObject());

                // name
                item.add(new Label("name", item.getModelObject()));

                // text field
                TextField<String> textField = new TextField<String>("field",
                        new FieldFieldModel(item.getModelObject()));
                textField.setVisible(!isContentType);
                item.add(textField);

                // contentType select field
                DropDownChoice<String> contentType;
                if (isContentType) {
                    IOProviderDescriptor pf = HaleIO.findIOProviderFactory(InstanceWriter.class, null,
                            getTarget().getProviderId());
                    List<String> types = new ArrayList<String>();
                    for (IContentType type : pf.getSupportedTypes()) {
                        types.add(type.getId());
                    }
                    contentType = new DropDownChoice<String>("contentType",
                            new FieldFieldModel(item.getModelObject()), types, new ContentTypeChoiceRenderer());
                } else {
                    contentType = new DropDownChoice<String>("contentType", new ArrayList<String>());
                    contentType.setVisible(false);
                }
                item.add(contentType);
            }

        };
        config.add(parameterView);

        // update parameter panel on target selection change
        selectTarget.add(new AjaxFormComponentUpdatingBehavior("onchange") {

            private static final long serialVersionUID = 8004015871380712045L;

            @Override
            protected void onUpdate(AjaxRequestTarget target) {
                // update config panel

                target.add(config);
            }

        });
    }

    /**
     * @see Form#onSubmit()
     */
    @Override
    protected void onSubmit() {
        List<FileUpload> uploads = file.getFileUploads();
        if (uploads == null || uploads.isEmpty()) {
            error("Please specify files to transform.");
            return;
        }

        final TransformationWorkspace workspace = new TransformationWorkspace();

        List<InstanceReader> readers = Lists.transform(uploads, new Function<FileUpload, InstanceReader>() {

            private int count;

            @Override
            public InstanceReader apply(@Nullable final FileUpload input) {
                /*
                 * Copy uploaded file to source folder, because the
                 * input stream retrieved from the FileUpload is
                 * automatically closed with the end of the request.
                 */
                File file = new File(workspace.getSourceFolder(), (count++) + "_" + input.getClientFileName());
                try {
                    input.writeTo(file);
                } catch (IOException e) {
                    throw new IllegalStateException("Unable to read uploaded source file", e);
                }

                InstanceReader reader = null;
                try {
                    LocatableInputSupplier<? extends InputStream> in = new FileIOSupplier(file);
                    reader = HaleIO.findIOProvider(InstanceReader.class, in, input.getClientFileName());
                    if (reader != null) {
                        reader.setSource(in);
                    }
                } catch (Exception e) {
                    throw new IllegalStateException("Unable to read uploaded source file", e);
                }
                if (reader == null) {
                    throw new IllegalStateException("Could not find I/O provider for source file.");
                }
                return reader;
            }
        });

        try {
            workspace.transform(projectId, readers, target);
            setResponsePage(StatusPage.class,
                    new PageParameters().add(StatusPage.PARAMETER_WORKSPACE, workspace.getId()));
        } catch (Exception e) {
            log.error("Error launching transformation process", e);
            error("Error launching transformation process");
            workspace.delete();
        }
    }

    /**
     * @return the target
     */
    public IOConfiguration getTarget() {
        return target;
    }

    /**
     * @param target the target to set
     */
    public void setTarget(IOConfiguration target) {
        this.target = target;
    }

}