de.tudarmstadt.ukp.clarin.webanno.project.page.ProjectPage.java Source code

Java tutorial

Introduction

Here is the source code for de.tudarmstadt.ukp.clarin.webanno.project.page.ProjectPage.java

Source

/*******************************************************************************
 * Copyright 2012
 * Ubiquitous Knowledge Processing (UKP) Lab and FG Language Technology
 * Technische Universitt Darmstadt
 *
 * 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 de.tudarmstadt.ukp.clarin.webanno.project.page;

import static org.apache.commons.collections.CollectionUtils.isEmpty;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.wicket.Component;
import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
import org.apache.wicket.extensions.ajax.markup.html.tabs.AjaxTabbedPanel;
import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
import org.apache.wicket.extensions.markup.html.tabs.ITab;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.form.ChoiceRenderer;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.ListChoice;
import org.apache.wicket.markup.html.form.RadioChoice;
import org.apache.wicket.markup.html.form.TextArea;
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.panel.Panel;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;
import org.springframework.security.core.context.SecurityContextHolder;

import de.tudarmstadt.ukp.clarin.webanno.api.AnnotationService;
import de.tudarmstadt.ukp.clarin.webanno.api.RepositoryService;
import de.tudarmstadt.ukp.clarin.webanno.api.UserDao;
import de.tudarmstadt.ukp.clarin.webanno.api.dao.ZipUtils;
import de.tudarmstadt.ukp.clarin.webanno.api.dao.SecurityUtil;
import de.tudarmstadt.ukp.clarin.webanno.automation.AutomationService;
import de.tudarmstadt.ukp.clarin.webanno.automation.project.ProjectMiraTemplatePanel;
import de.tudarmstadt.ukp.clarin.webanno.model.AnnotationFeature;
import de.tudarmstadt.ukp.clarin.webanno.model.MiraTemplate;
import de.tudarmstadt.ukp.clarin.webanno.model.Mode;
import de.tudarmstadt.ukp.clarin.webanno.model.PermissionLevel;
import de.tudarmstadt.ukp.clarin.webanno.model.Project;
import de.tudarmstadt.ukp.clarin.webanno.model.ProjectPermission;
import de.tudarmstadt.ukp.clarin.webanno.model.Role;
import de.tudarmstadt.ukp.clarin.webanno.model.ScriptDirection;
import de.tudarmstadt.ukp.clarin.webanno.model.SourceDocument;
import de.tudarmstadt.ukp.clarin.webanno.model.Tag;
import de.tudarmstadt.ukp.clarin.webanno.model.TagSet;
import de.tudarmstadt.ukp.clarin.webanno.model.User;
import de.tudarmstadt.ukp.clarin.webanno.support.EntityModel;
import de.tudarmstadt.ukp.clarin.webanno.support.JSONUtil;
import de.tudarmstadt.ukp.clarin.webanno.webapp.home.page.ApplicationPageBase;

/**
 * This is the main page for Project Settings. The Page has Four Panels. The
 * {@link AnnotationGuideLinePanel} is used to update documents to a project. The
 * {@code ProjectDetailsPanel} used for updating Project details such as descriptions of a project
 * and name of the Project The {@link ProjectTagSetsPanel} is used to add {@link TagSet} and
 * {@link Tag} details to a Project as well as updating them The {@link ProjectUsersPanel} is used
 * to update {@link User} to a Project
 *
 * @author Seid Muhie Yimam
 * @author Richard Eckart de Castilho
 *
 */
public class ProjectPage extends ApplicationPageBase {
    private static final long serialVersionUID = -2102136855109258306L;

    private static final Log LOG = LogFactory.getLog(ProjectPage.class);

    @SpringBean(name = "annotationService")
    private AnnotationService annotationService;

    @SpringBean(name = "automationService")
    private AutomationService automationService;

    @SpringBean(name = "documentRepository")
    private RepositoryService repository;

    @SpringBean(name = "userRepository")
    private UserDao userRepository;

    public static ProjectSelectionForm projectSelectionForm;
    public static ProjectDetailForm projectDetailForm;
    private final ImportProjectForm importProjectForm;

    private RadioChoice<Mode> projectType;
    public static boolean visible = true;

    public ProjectPage() {
        projectSelectionForm = new ProjectSelectionForm("projectSelectionForm");

        projectDetailForm = new ProjectDetailForm("projectDetailForm");
        projectDetailForm.setOutputMarkupPlaceholderTag(true);
        projectDetailForm.setVisible(false);

        importProjectForm = new ImportProjectForm("importProjectForm");

        add(projectSelectionForm);
        add(importProjectForm);
        add(projectDetailForm);

        MetaDataRoleAuthorizationStrategy.authorize(importProjectForm, Component.RENDER, "ROLE_ADMIN");
    }

    class ProjectSelectionForm extends Form<SelectionModel> {
        private static final long serialVersionUID = -1L;
        private Button createProject;

        public ProjectSelectionForm(String id) {
            super(id, new CompoundPropertyModel<SelectionModel>(new SelectionModel()));

            add(createProject = new Button("create", new ResourceModel("label")) {
                private static final long serialVersionUID = 1L;

                @Override
                public void onSubmit() {
                    projectDetailForm.setModelObject(new Project());
                    projectDetailForm.setVisible(true);
                    ProjectSelectionForm.this.setModelObject(new SelectionModel());
                    if (projectType != null) {
                        projectType.setEnabled(true);
                    }
                }
            });

            MetaDataRoleAuthorizationStrategy.authorize(createProject, Component.RENDER, StringUtils
                    .join(new String[] { Role.ROLE_ADMIN.name(), Role.ROLE_PROJECT_CREATOR.name() }, ","));

            add(new ListChoice<Project>("project") {
                private static final long serialVersionUID = 1L;

                {
                    setChoices(new LoadableDetachableModel<List<Project>>() {
                        private static final long serialVersionUID = 1L;

                        @Override
                        protected List<Project> load() {
                            return repository.listAccessibleProjects();
                        }
                    });
                    setChoiceRenderer(new ChoiceRenderer<Project>("name"));
                    setNullValid(false);
                }

                @Override
                protected void onSelectionChanged(Project aNewSelection) {
                    if (aNewSelection != null) {
                        projectDetailForm.setModelObject(aNewSelection);
                        projectDetailForm.projectModel.setObject(aNewSelection);
                        projectDetailForm.setVisible(true);

                        projectDetailForm.allTabs.setSelectedTab(0);
                        RequestCycle.get().setResponsePage(getPage());
                        ProjectSelectionForm.this.setVisible(true);
                    }
                    if (projectType != null) {
                        projectType.setEnabled(false);
                    }
                }

                @Override
                protected boolean wantOnSelectionChangedNotifications() {
                    return true;
                }

                @Override
                protected CharSequence getDefaultChoice(String aSelectedValue) {
                    return "";
                }
            });
        }
    }

    static public class SelectionModel implements Serializable {
        private static final long serialVersionUID = -1L;

        public Project project;
        public List<String> documents;
        public List<String> permissionLevels;
        public User user;
    }

    private class ImportProjectForm extends Form<ImportProjectModel> {
        private static final long serialVersionUID = -6361609153142402692L;
        private FileUploadField fileUpload;

        @SuppressWarnings({ "unchecked", "rawtypes" })
        public ImportProjectForm(String id) {
            super(id, new CompoundPropertyModel<>(new ImportProjectModel()));
            add(new CheckBox("generateUsers"));
            add(fileUpload = new FileUploadField("content", new Model()));

            add(new Button("importProject", new ResourceModel("label")) {
                private static final long serialVersionUID = 1L;

                @Override
                public void onSubmit() {
                    List<FileUpload> exportedProjects = fileUpload.getFileUploads();
                    if (isEmpty(exportedProjects)) {
                        error("Please choose appropriate project/s in zip format");
                    } else {
                        actionImportProject(exportedProjects,
                                ImportProjectForm.this.getModelObject().generateUsers);
                    }
                }
            });
        }
    }

    private class ImportProjectModel implements Serializable {
        private static final long serialVersionUID = -5858027181097577052L;

        boolean generateUsers = true;
    }

    public class ProjectDetailForm extends Form<Project> {
        private static final long serialVersionUID = -1L;

        AbstractTab details;
        AbstractTab users;
        AbstractTab layers;
        AbstractTab tagSets;
        AbstractTab documents;
        @SuppressWarnings("rawtypes")
        AjaxTabbedPanel allTabs;

        public ProjectDetailForm(String id) {
            super(id, new CompoundPropertyModel<Project>(new EntityModel<Project>(new Project())));

            List<ITab> tabs = new ArrayList<ITab>();
            tabs.add(details = new AbstractTab(new Model<String>("Details")) {
                private static final long serialVersionUID = 6703144434578403272L;

                @Override
                public Panel getPanel(String panelId) {
                    return new ProjectDetailsPanel(panelId);
                }

                @Override
                public boolean isVisible() {
                    return visible;
                }
            });

            tabs.add(users = new AbstractTab(new Model<String>("Users")) {
                private static final long serialVersionUID = 7160734867954315366L;

                @Override
                public Panel getPanel(String panelId) {
                    return new ProjectUsersPanel(panelId, projectModel);
                }

                @Override
                public boolean isVisible() {
                    return projectModel.getObject().getId() != 0 && visible;
                }
            });

            tabs.add(documents = new AbstractTab(new Model<String>("Documents")) {
                private static final long serialVersionUID = 1170760600317199418L;

                @Override
                public Panel getPanel(String panelId) {
                    return new ProjectDocumentsPanel(panelId, projectModel);
                }

                @Override
                public boolean isVisible() {
                    return projectModel.getObject().getId() != 0 && visible;
                }
            });

            tabs.add(layers = new AbstractTab(new Model<String>("Layers")) {
                private static final long serialVersionUID = 3274065112505097898L;

                @Override
                public Panel getPanel(String panelId) {
                    return new ProjectLayersPanel(panelId, projectModel);
                }

                @Override
                public boolean isVisible() {
                    return projectModel.getObject().getId() != 0 && visible;
                }
            });

            tabs.add(tagSets = new AbstractTab(new Model<String>("Tagsets")) {
                private static final long serialVersionUID = -3205723896786674220L;

                @Override
                public Panel getPanel(String panelId) {
                    return new ProjectTagSetsPanel(panelId, projectModel);
                }

                @Override
                public boolean isVisible() {
                    return projectModel.getObject().getId() != 0 && visible;
                }
            });

            tabs.add(new AbstractTab(new Model<String>("Guidelines")) {
                private static final long serialVersionUID = 7887973231065189200L;

                @Override
                public Panel getPanel(String panelId) {
                    return new AnnotationGuideLinePanel(panelId, projectModel);
                }

                @Override
                public boolean isVisible() {
                    return projectModel.getObject().getId() != 0 && visible;
                }
            });

            tabs.add(new AbstractTab(new Model<String>("Export")) {

                private static final long serialVersionUID = 788812791376373350L;

                @Override
                public Panel getPanel(String panelId) {
                    return new ProjectExportPanel(panelId, projectModel);
                }

                @Override
                public boolean isVisible() {
                    return projectModel.getObject().getId() != 0;

                }
            });

            tabs.add(new AbstractTab(new Model<String>("Automation")) {

                private static final long serialVersionUID = 788812791376373350L;

                @Override
                public Panel getPanel(String panelId) {
                    return new ProjectMiraTemplatePanel(panelId, projectModel);
                }

                @Override
                public boolean isVisible() {
                    return projectModel.getObject().getId() != 0
                            && projectModel.getObject().getMode().equals(Mode.AUTOMATION) && visible;

                }
            });
            add(allTabs = (AjaxTabbedPanel) new AjaxTabbedPanel<ITab>("tabs", tabs)
                    .setOutputMarkupPlaceholderTag(true));
            ProjectDetailForm.this.setMultiPart(true);
        }

        // Update the project mode, that will be shared among TABS
        // Better way of sharing data
        // http://stackoverflow.com/questions/6532178/wicket-persistent-object-between-panels
        Model<Project> projectModel = new Model<Project>() {
            private static final long serialVersionUID = -6394439155356911110L;

            @Override
            public Project getObject() {
                return projectDetailForm.getModelObject();
            }
        };
    }

    private class ProjectDetailsPanel extends Panel {
        private static final long serialVersionUID = 1118880151557285316L;

        @SuppressWarnings("unchecked")
        public ProjectDetailsPanel(String id) {
            super(id);
            add(new TextField<String>("name").setRequired(true));

            add(new TextArea<String>("description").setOutputMarkupPlaceholderTag(true));

            add(projectType = (RadioChoice<Mode>) new RadioChoice<Mode>("mode",
                    Arrays.asList(new Mode[] { Mode.ANNOTATION, Mode.AUTOMATION, Mode.CORRECTION }))
                            .setEnabled(projectDetailForm.getModelObject().getId() == 0));

            add(new DropDownChoice<ScriptDirection>("scriptDirection", Arrays.asList(ScriptDirection.values())));

            add(new Button("save", new ResourceModel("label")) {

                private static final long serialVersionUID = 1L;

                @Override
                public void onSubmit() {
                    Project project = projectDetailForm.getModelObject();
                    if (!ImportUtil.isNameValid(project.getName())) {

                        // Maintain already loaded project and selected Users
                        // Hence Illegal Project modification (limited
                        // privilege, illegal
                        // project
                        // name,...) preserves the original one
                        if (project.getId() != 0) {
                            project.setName(ImportUtil.validName(project.getName()));
                        }
                        error("Project name shouldn't contain characters such as /\\*?&!$+[^]");
                        LOG.error("Project name shouldn't contain characters such as /\\*?&!$+[^]");
                        return;
                    }
                    if (repository.existsProject(project.getName()) && project.getId() == 0) {
                        error("Another project with name [" + project.getName() + "] exists");
                        return;
                    }

                    if (repository.existsProject(project.getName()) && project.getId() != 0) {
                        error("project updated with name [" + project.getName() + "]");
                        return;
                    }
                    try {
                        String username = SecurityContextHolder.getContext().getAuthentication().getName();
                        User user = userRepository.get(username);
                        repository.createProject(project, user);

                        // If the project was created by a user (not a global admin), then add this
                        // user as a project admin so that the user can see and edit the project.
                        if (SecurityUtil.isProjectCreator(repository, user)) {
                            ProjectPermission permission = new ProjectPermission();
                            permission.setLevel(PermissionLevel.ADMIN);
                            permission.setProject(project);
                            permission.setUser(username);
                            repository.createProjectPermission(permission);
                        }

                        annotationService.initializeTypesForProject(project, user, new String[] {}, new String[] {},
                                new String[] {}, new String[] {}, new String[] {}, new String[] {}, new String[] {},
                                new String[] {});
                        projectDetailForm.setVisible(true);
                        SelectionModel selectionModel = new SelectionModel();
                        selectionModel.project = project;
                        projectSelectionForm.setModelObject(selectionModel);
                    } catch (IOException e) {
                        error("Project repository path not found " + ":" + ExceptionUtils.getRootCauseMessage(e));
                        LOG.error(
                                "Project repository path not found " + ":" + ExceptionUtils.getRootCauseMessage(e));
                    }
                }
            });
            add(new Button("remove", new ResourceModel("label")) {
                private static final long serialVersionUID = 1L;

                @Override
                public void onSubmit() {
                    Project project = projectDetailForm.getModelObject();
                    if (project.getId() == 0) {

                    }
                    try {
                        String username = SecurityContextHolder.getContext().getAuthentication().getName();
                        User user = userRepository.get(username);

                        // BEGIN: Remove automation stuff
                        for (MiraTemplate template : automationService.listMiraTemplates(project)) {
                            automationService.removeMiraTemplate(template);
                        }

                        for (SourceDocument document : automationService.listTabSepDocuments(project)) {
                            repository.removeSourceDocument(document);
                        }
                        // END: Remove automation stuff

                        repository.removeProject(project, user);
                        projectDetailForm.setVisible(false);
                    } catch (IOException e) {
                        LOG.error("Unable to remove project :" + ExceptionUtils.getRootCauseMessage(e));
                        error("Unable to remove project " + ":" + ExceptionUtils.getRootCauseMessage(e));
                    }
                }
            });
        }
    }

    private void actionImportProject(List<FileUpload> exportedProjects, boolean aGenerateUsers) {
        Project importedProject = new Project();
        // import multiple projects!
        for (FileUpload exportedProject : exportedProjects) {
            InputStream tagInputStream;
            try {
                tagInputStream = exportedProject.getInputStream();
                if (!ZipUtils.isZipStream(tagInputStream)) {
                    error("Invalid ZIP file");
                    return;
                }
                File zipFfile = exportedProject.writeToTempFile();
                if (!ImportUtil.isZipValidWebanno(zipFfile)) {
                    error("Incompatible to webanno ZIP file");
                }
                ZipFile zip = new ZipFile(zipFfile);
                InputStream projectInputStream = null;
                for (Enumeration zipEnumerate = zip.entries(); zipEnumerate.hasMoreElements();) {
                    ZipEntry entry = (ZipEntry) zipEnumerate.nextElement();
                    if (entry.toString().replace("/", "").startsWith(ImportUtil.EXPORTED_PROJECT)
                            && entry.toString().replace("/", "").endsWith(".json")) {
                        projectInputStream = zip.getInputStream(entry);
                        break;
                    }
                }

                // projectInputStream =
                // uploadedFile.getInputStream();
                String text = IOUtils.toString(projectInputStream, "UTF-8");
                de.tudarmstadt.ukp.clarin.webanno.model.export.Project importedProjectSetting = JSONUtil
                        .getJsonConverter().getObjectMapper()
                        .readValue(text, de.tudarmstadt.ukp.clarin.webanno.model.export.Project.class);

                importedProject = ImportUtil.createProject(importedProjectSetting, repository, userRepository);

                Map<de.tudarmstadt.ukp.clarin.webanno.model.export.AnnotationFeature, AnnotationFeature> featuresMap = ImportUtil
                        .createLayer(importedProject, importedProjectSetting, userRepository, annotationService);
                ImportUtil.createSourceDocument(importedProjectSetting, importedProject, repository, userRepository,
                        featuresMap);
                ImportUtil.createMiraTemplate(importedProjectSetting, automationService, featuresMap);
                ImportUtil.createCrowdJob(importedProjectSetting, repository, importedProject);

                ImportUtil.createAnnotationDocument(importedProjectSetting, importedProject, repository);
                ImportUtil.createProjectPermission(importedProjectSetting, importedProject, repository,
                        aGenerateUsers, userRepository);
                /*
                 * for (TagSet tagset : importedProjectSetting.getTagSets()) {
                 * ImportUtil.createTagset(importedProject, tagset, projectRepository,
                 * annotationService); }
                 */
                // add source document content
                ImportUtil.createSourceDocumentContent(zip, importedProject, repository);
                // add annotation document content
                ImportUtil.createAnnotationDocumentContent(zip, importedProject, repository);
                // create curation document content
                ImportUtil.createCurationDocumentContent(zip, importedProject, repository);
                // create project log
                ImportUtil.createProjectLog(zip, importedProject, repository);
                // create project guideline
                ImportUtil.createProjectGuideline(zip, importedProject, repository);
                // cretae project META-INF
                ImportUtil.createProjectMetaInf(zip, importedProject, repository);
            } catch (IOException e) {
                error("Error Importing Project " + ExceptionUtils.getRootCauseMessage(e));
            }
        }
        projectDetailForm.setModelObject(importedProject);
        SelectionModel selectedProjectModel = new SelectionModel();
        selectedProjectModel.project = importedProject;
        projectSelectionForm.setModelObject(selectedProjectModel);
        projectDetailForm.setVisible(true);
        RequestCycle.get().setResponsePage(getPage());
    }
}