cz.zcu.kiv.eegdatabase.wui.ui.experiments.components.ExperimentPackageManagePanel.java Source code

Java tutorial

Introduction

Here is the source code for cz.zcu.kiv.eegdatabase.wui.ui.experiments.components.ExperimentPackageManagePanel.java

Source

/*******************************************************************************
 * This file is part of the EEG-database project
 * 
 *   ==========================================
 *  
 *   Copyright (C) 2013 by University of West Bohemia (http://www.zcu.cz/en/)
 *  
 *  ***********************************************************************************************************************
 *  
 *   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.
 *  
 *  ***********************************************************************************************************************
 *  
 *   ExperimentPackageManagePanel.java, 2013/10/02 00:01 Jakub Rinkes
 ******************************************************************************/
package cz.zcu.kiv.eegdatabase.wui.ui.experiments.components;

import cz.zcu.kiv.eegdatabase.data.pojo.*;
import cz.zcu.kiv.eegdatabase.wui.components.table.CheckBoxColumn;
import cz.zcu.kiv.eegdatabase.wui.components.table.TimestampPropertyColumn;
import cz.zcu.kiv.eegdatabase.wui.components.table.ViewLinkPanel;
import cz.zcu.kiv.eegdatabase.wui.components.utils.ResourceUtils;
import cz.zcu.kiv.eegdatabase.wui.core.common.KeywordsFacade;
import cz.zcu.kiv.eegdatabase.wui.core.experimentpackage.ExperimentPackageFacade;
import cz.zcu.kiv.eegdatabase.wui.core.experimentpackage.ExperimentPackageLicenseFacade;
import cz.zcu.kiv.eegdatabase.wui.core.experiments.ExperimentsFacade;
import cz.zcu.kiv.eegdatabase.wui.core.license.LicenseFacade;
import cz.zcu.kiv.eegdatabase.wui.ui.experiments.ExperimentsDetailPage;
import cz.zcu.kiv.eegdatabase.wui.ui.experiments.ListExperimentsDataProvider;
import cz.zcu.kiv.eegdatabase.wui.ui.licenses.components.LicensePriceForm;
import cz.zcu.kiv.eegdatabase.wui.ui.licenses.components.ViewLicensePanel;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackDefaultDataTable;
import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
import org.apache.wicket.extensions.model.AbstractCheckBoxModel;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.model.*;
import org.apache.wicket.spring.injection.annot.SpringBean;

import java.math.BigDecimal;
import java.util.*;

/**
 * Panel for experiment package management. Adding/removing experiments and
 * licenses.
 *
 * @author Jakub Danek
 * @author Jakub Krauz
 */
@SuppressWarnings("serial")
public class ExperimentPackageManagePanel extends Panel {

    protected Log log = LogFactory.getLog(getClass());

    private static final int EXPERIMENTS_PER_PAGE = 10;

    @SpringBean
    private ExperimentsFacade experimentsFacade;

    @SpringBean
    private ExperimentPackageFacade experimentPackageFacade;

    @SpringBean
    private LicenseFacade licenseFacade;

    @SpringBean
    private ExperimentPackageLicenseFacade experimentPackageLicenseFacade;

    @SpringBean
    private KeywordsFacade keywordsFacade;

    /** Main model of the component - experiment package */
    private IModel<ExperimentPackage> epModel;

    /** Set of selected experiments. */
    private Set<Experiment> selectedExperiments;

    /** List of experiments attached to the package */
    private IModel<List<Experiment>> experimentsModel;

    /** List of experiments which can be added to the package */
    private IModel<List<Experiment>> experimentsToAddModel;

    private IModel<Keywords> keywordsModel;

    /** Model of the viewLicenseWindow */
    private IModel<License> licenseModel = new Model<License>();

    //containers
    private WebMarkupContainer experimentListCont;
    private WebMarkupContainer header, footer;
    private ModalWindow addExperimentsWindow;
    private ModalWindow addLicenseWindow;
    private ModalWindow viewLicenseWindow;

    /**
     *
     * @param id component id
     * @param model model with the experiment package for which the info shall
     * be displayed
     */
    public ExperimentPackageManagePanel(String id, IModel<ExperimentPackage> model) {
        super(id);

        this.epModel = model;
        this.selectedExperiments = new HashSet<Experiment>();

        experimentListCont = new WebMarkupContainer("experimentListCont");
        experimentListCont.setOutputMarkupPlaceholderTag(true);
        this.add(experimentListCont);
        keywordsModel = this.keywordsToPackage();

        this.addHeader();
        this.add((new Label("keywords", new PropertyModel(keywordsModel, "keywordsText"))));
        this.addFooter();
        this.addExperimentListToCont(experimentListCont);
        this.addExperimentsAddWindow();
        this.addExperimentsViewWindow();
        this.addLicenseAddWindow();
    }

    private void addExperimentsViewWindow() {
        viewLicenseWindow = new ModalWindow("viewLicenseWindow");
        viewLicenseWindow.setAutoSize(true);
        viewLicenseWindow.setResizable(false);
        viewLicenseWindow.setMinimalWidth(600);
        viewLicenseWindow.setWidthUnit("px");
        viewLicenseWindow.showUnloadConfirmation(false);
        add(viewLicenseWindow);

        viewLicenseWindow.setContent(new ViewLicensePanel(viewLicenseWindow.getContentId(), licenseModel, true) {
            @Override
            protected void onRemoveAction(IModel<License> model, AjaxRequestTarget target, Form<?> form) {
                licenseFacade.removeLicenseFromPackage(model.getObject(), epModel.getObject());
                ModalWindow.closeCurrent(target);
                target.add(header);
                experimentsToAddModel.detach(); // list of experiments to add must be reloaded for the actual set of licenses
            }
        });
        viewLicenseWindow.setTitle(ResourceUtils.getModel("dataTable.heading.licenseTitle"));
    }

    /**
     * Add window which allows to add experiments to the package.
     */
    private void addExperimentsAddWindow() {
        addExperimentsWindow = new ModalWindow("addExperimentsWindow");
        addExperimentsWindow.setAutoSize(true);
        addExperimentsWindow.setResizable(false);
        addExperimentsWindow.setMinimalWidth(600);
        addExperimentsWindow.setWidthUnit("px");

        experimentsToAddModel = this.listExperimentsToAdd();

        Panel content = new ExperimentListForm(addExperimentsWindow.getContentId(),
                ResourceUtils.getModel("pageTitle.addExperimenToPackage"), experimentsToAddModel) {
            @Override
            protected void onSubmitAction(List<Experiment> selectedExperiments, AjaxRequestTarget target,
                    Form<?> form) {
                experimentPackageFacade.addExperimentsToPackage(selectedExperiments, epModel.getObject());
                ModalWindow.closeCurrent(target);
                experimentsModel.detach();
                experimentsToAddModel.detach();
                target.add(experimentListCont);
            }

            @Override
            protected void onCancelAction(List<Experiment> selectedExperiments, AjaxRequestTarget target,
                    Form<?> form) {
                ModalWindow.closeCurrent(target);
                target.add(experimentListCont);
            }
        };

        addExperimentsWindow.setContent(content);
        this.add(addExperimentsWindow);
    }

    /**
     *
     * @return list of experiments that can be added to the package
     */
    private IModel<List<Experiment>> listExperimentsToAdd() {
        return new LoadableDetachableModel<List<Experiment>>() {

            @Override
            protected List<Experiment> load() {
                ExperimentPackage pckg = epModel.getObject();
                List<Experiment> list = experimentsFacade.getExperimentsWithoutPackage(pckg);

                // remove all experiments that do not match package licenses
                // TODO doing this in one database query would be more efficient
                final List<License> pckgLicenses = licenseFacade.getLicensesForPackage(pckg);
                Iterator<Experiment> it = list.iterator();
                while (it.hasNext()) {
                    List<License> expLicenses = licenseFacade.getLicensesForExperiment(it.next().getExperimentId());
                    if (!expLicenses.containsAll(pckgLicenses))
                        it.remove();
                }

                return list;
            }

        };
    }

    private IModel<Keywords> keywordsToPackage() {
        return new LoadableDetachableModel<Keywords>() {
            @Override
            protected Keywords load() {
                List<Integer> list = keywordsFacade.getKeywordsFromPackage(epModel.getObject());
                if (list.isEmpty()) {
                    return new Keywords();
                } else {
                    return keywordsFacade.read(list.get(0));
                }
            }
        };
    }

    /**
     * Add components header - title, controls
     */
    private void addHeader() {
        header = new WebMarkupContainer("header");
        header.setOutputMarkupId(true);
        this.add(header);

        header.add(new Label("packageTitle", new PropertyModel<String>(epModel, "name")));

        header.add(createRemovePackageLink("removePackageLink"));

        this.addLicenseList(header);
    }

    private void addFooter() {
        footer = new WebMarkupContainer("footer");
        footer.setOutputMarkupId(true);
        this.add(footer);

        footer.add(createVisibilityLink("showListLink", true));
        footer.add(createVisibilityLink("hideListLink", false));
        footer.add(createRemoveSelectedLink("removeSelectedLink"));
        footer.add(createAddExperimentsLink("addExperimentsLink"));
    }

    private Link<?> createRemovePackageLink(String id) {
        Link<?> removeLink = new Link<Void>(id) {
            @Override
            public void onClick() {
                ExperimentPackage pck = epModel.getObject();
                List<Integer> list = keywordsFacade.getKeywordsFromPackage(pck);
                for (Integer id : list) {
                    keywordsFacade.delete(keywordsFacade.read(id));
                }
                experimentPackageFacade.removeExperimentPackage(pck);
                setResponsePage(this.getPage().getPageClass(), this.getPage().getPageParameters());
            }
        };

        removeLink.add(new Label("label", ResourceUtils.getModel("button.remove.package")));

        return removeLink;
    }

    /**
     * Adds list of licenses attached to the package.
     *
     * @param cont container to add the list to
     */
    private void addLicenseList(WebMarkupContainer cont) {

        IModel<List<ExperimentPackageLicense>> licenses = new LoadableDetachableModel<List<ExperimentPackageLicense>>() {
            @Override
            protected List<ExperimentPackageLicense> load() {
                return experimentPackageLicenseFacade.getExperimentPackageLicensesForPackage(epModel.getObject());
            }
        };

        ListView<ExperimentPackageLicense> view = new ListView<ExperimentPackageLicense>("licenseView", licenses) {
            @Override
            protected void populateItem(ListItem<ExperimentPackageLicense> item) {
                AjaxLink<License> link = new AjaxLink<License>("licenseItem",
                        new Model<License>(item.getModelObject().getLicense())) {
                    @Override
                    public void onClick(AjaxRequestTarget target) {
                        licenseModel.setObject(this.getModelObject());
                        viewLicenseWindow.show(target);
                    }
                };
                link.add(new Label("licenseItemLabel",
                        new PropertyModel<String>(item.getModelObject().getLicense(), "title")));
                item.add(link);
                item.add(new Label("price", new Model<BigDecimal>(item.getModelObject().getPrice())));
            }
        };

        AjaxLink<Void> link = new AjaxLink<Void>("addLicenseLink") {
            @Override
            public void onClick(AjaxRequestTarget target) {
                addLicenseWindow.show(target);
            }
        };

        cont.add(link);
        cont.add(view);
    }

    /**
     * Add window which allows to add new license to the package.
     */
    private void addLicenseAddWindow() {
        addLicenseWindow = new ModalWindow("addLicenseWindow");
        addLicenseWindow.setAutoSize(true);
        addLicenseWindow.setResizable(false);
        addLicenseWindow.setMinimalWidth(600);
        addLicenseWindow.setMinimalHeight(400);
        addLicenseWindow.setWidthUnit("px");
        addLicenseWindow.showUnloadConfirmation(false);

        // prepare list of licenses not associated with the package yet
        IModel<List<License>> licenses = new LoadableDetachableModel<List<License>>() {
            @Override
            protected List<License> load() {
                List<License> list = licenseFacade.getAllRecords();
                list.removeAll(licenseFacade.getLicensesForPackage(epModel.getObject()));
                return list;
            }
        };

        LicensePriceForm addLicenseForm = new LicensePriceForm(addLicenseWindow.getContentId(), licenses) {

            @Override
            protected void onSubmitAction(License license, BigDecimal price, AjaxRequestTarget target,
                    Form<?> form) {
                ExperimentPackageLicense expPacLic = new ExperimentPackageLicense();
                expPacLic.setExperimentPackage(epModel.getObject());
                expPacLic.setLicense(license);
                expPacLic.setPrice(price);
                experimentPackageLicenseFacade.create(expPacLic);
                ModalWindow.closeCurrent(target);
                target.add(header);
                experimentsToAddModel.detach(); // list of experiments to add must be reloaded for the actual set of licenses
                // TODO check all experiments contained in the package for the new license
            }

            @Override
            protected void onCancelAction(AjaxRequestTarget target, Form<?> form) {
                ModalWindow.closeCurrent(target);
                target.add(header);
            }

        };

        addLicenseWindow.setContent(addLicenseForm);
        this.add(addLicenseWindow);
    }

    /**
     * returns link which initializes the action of adding experiments to
     * package
     *
     * @param id component id
     * @return the link
     */
    private AjaxLink createAddExperimentsLink(String id) {
        AjaxLink link = new AjaxLink(id) {
            @Override
            public void onClick(AjaxRequestTarget target) {
                addExperimentsWindow.show(target);
            }
        };

        link.add(new Label("label", new StringResourceModel("button.add.experiment", this, null)));
        return link;
    }

    /**
     * Creates link which provides action for removing selected experiments from
     * the package
     *
     * @param id link component id
     * @return the link
     */
    private Link createRemoveSelectedLink(String id) {
        Link link = new Link(id) {
            @Override
            public void onClick() {
                experimentPackageFacade.removeExperimentsFromPackage(new ArrayList(selectedExperiments),
                        epModel.getObject());
            }
        };

        link.add(new Label("label", new StringResourceModel("button.removeSelected", this, null)));
        return link;
    }

    /**
     * Create link which changes visibility settings of the experimentListCont
     * container
     *
     * @param id link's id
     * @param makeVisible makes the container visible or invisible?
     * @return ajax link
     */
    private AjaxLink createVisibilityLink(String id, boolean makeVisible) {
        AjaxLink link = new AjaxLink<Boolean>(id, new Model<Boolean>(makeVisible)) {
            @Override
            public void onClick(AjaxRequestTarget target) {
                ExperimentPackageManagePanel.this.experimentListCont.setVisible(this.getModelObject());
                target.add(ExperimentPackageManagePanel.this.experimentListCont);
                target.add(footer);
            }

            @Override
            protected void onConfigure() {
                super.onConfigure();

                boolean contVisible = ExperimentPackageManagePanel.this.experimentListCont.isVisible();
                if (this.getModelObject()) {
                    //link for making cont visible is accessible only if the cont
                    //is currently invisible
                    this.setVisible(!contVisible);
                } else {
                    //and vice versa
                    this.setVisible(contVisible);
                }
            }
        };

        String resourceKey = makeVisible ? "button.show" : "button.hide";

        link.add(new Label("linkLabel", new StringResourceModel(resourceKey, this, null)));

        return link;
    }

    /**
     * Add view for the list of experiments to a container given
     *
     * @param cont the container
     */
    private void addExperimentListToCont(WebMarkupContainer cont) {
        List<? extends IColumn<Experiment, String>> columns = this.createListColumns();

        experimentsModel = new LoadableDetachableModel<List<Experiment>>() {
            @Override
            protected List<Experiment> load() {
                return experimentsFacade.getExperimentsByPackage(epModel.getObject().getExperimentPackageId());
            }
        };

        DataTable<Experiment, String> list = new AjaxFallbackDefaultDataTable<Experiment, String>("list", columns,
                new ListExperimentsDataProvider(experimentsModel), EXPERIMENTS_PER_PAGE);

        cont.add(list);
    }

    /**
     *
     * @return list of columns the table of experiments shall display
     */
    private List<? extends IColumn<Experiment, String>> createListColumns() {
        List<IColumn<Experiment, String>> columns = new ArrayList<IColumn<Experiment, String>>();

        columns.add(new CheckBoxColumn<Experiment, String>(Model.of("")) {
            @Override
            protected IModel<Boolean> newCheckBoxModel(final IModel<Experiment> rowModel) {
                return new AbstractCheckBoxModel() {
                    @Override
                    public boolean isSelected() {
                        return selectedExperiments.contains(rowModel.getObject());
                    }

                    @Override
                    public void select() {
                        selectedExperiments.add(rowModel.getObject());
                    }

                    @Override
                    public void unselect() {
                        selectedExperiments.add(rowModel.getObject());
                    }

                    @Override
                    public void detach() {
                        rowModel.detach();
                    }
                };

            }
        });
        columns.add(new PropertyColumn<Experiment, String>(ResourceUtils.getModel("dataTable.heading.number"),
                "experimentId", "experimentId"));
        columns.add(new PropertyColumn<Experiment, String>(
                ResourceUtils.getModel("dataTable.heading.scenarioTitle"), "scenario.title", "scenario.title"));
        columns.add(new PropertyColumn<Experiment, String>(ResourceUtils.getModel("dataTable.heading.date"),
                "startTime", "startTime"));
        columns.add(new PropertyColumn<Experiment, String>(ResourceUtils.getModel("dataTable.heading.gender"),
                "personBySubjectPersonId.gender", "personBySubjectPersonId.gender"));
        columns.add(new TimestampPropertyColumn<Experiment, String>(
                ResourceUtils.getModel("dataTable.heading.yearOfBirth"), "personBySubjectPersonId.dateOfBirth",
                "personBySubjectPersonId.dateOfBirth", "yyyy"));
        columns.add(new PropertyColumn<Experiment, String>(ResourceUtils.getModel("dataTable.heading.detail"), null,
                null) {
            @Override
            public void populateItem(Item<ICellPopulator<Experiment>> item, String componentId,
                    IModel<Experiment> rowModel) {
                item.add(new ViewLinkPanel(componentId, ExperimentsDetailPage.class, "experimentId", rowModel,
                        ResourceUtils.getModel("link.detail")));
            }
        });

        return columns;
    }
}