diff --git a/user-db-portlet/.gitignore b/user-db-portlet/.gitignore
new file mode 100644
index 0000000..cbc4e65
--- /dev/null
+++ b/user-db-portlet/.gitignore
@@ -0,0 +1,28 @@
+
+# Eclipse
+.classpath
+.project
+.settings/
+
+# VS Code
+.vscode
+
+# Intellij
+.idea/
+*.iml
+*.iws
+
+# Mac
+.DS_Store
+
+# Maven
+target/
+
+# Some of our applications generate logs, which should be ignored by git
+logs/
+
+# Other
+**/.factorypath
+
+# compiled Vaadin widgetsets
+src/main/webapp/VAADIN/widgetsets
\ No newline at end of file
diff --git a/user-db-portlet/.travis.settings.xml b/user-db-portlet/.travis.settings.xml
new file mode 100644
index 0000000..5c65a2e
--- /dev/null
+++ b/user-db-portlet/.travis.settings.xml
@@ -0,0 +1,14 @@
+
+
+
+ nexus-snapshots
+ ${env.MAVEN_REPO_USERNAME}
+ ${env.MAVEN_REPO_PASSWORD}
+
+
+ nexus-releases
+ ${env.MAVEN_REPO_USERNAME}
+ ${env.MAVEN_REPO_PASSWORD}
+
+
+
\ No newline at end of file
diff --git a/user-db-portlet/.travis.yml b/user-db-portlet/.travis.yml
new file mode 100644
index 0000000..1ee480e
--- /dev/null
+++ b/user-db-portlet/.travis.yml
@@ -0,0 +1,74 @@
+# Build script for Travis CI
+#
+
+# use fast-boot container-based hosts
+sudo: false
+dist: trusty
+
+# no need to check for oracle's java
+language: java
+jdk: openjdk8
+
+# speed up builds by caching maven local repository
+cache:
+ directories:
+ - "$HOME/.m2/repository"
+
+# as agreed in our SOP
+branches:
+ only:
+ - master
+ - development
+
+# added to make logs look cleaner, crisper, certified fresh
+before_install: unset _JAVA_OPTIONS
+
+# speed up builds by telling Travis that we don't need any special "installation"
+install: true
+
+# as agreed in our SOP, build everything (don't deploy, just try to 'mvn install' locally, which covers all phases)
+script: mvn --quiet --activate-profiles !development-build,!release-build --settings .travis.settings.xml clean cobertura:cobertura install
+# upload code coverage report, generate maven site (javadocs, documentation, static code analysis, etc.)
+after_success:
+- bash <(curl -s https://codecov.io/bash)
+- mvn --quiet --activate-profiles !development-build,!release-build --settings .travis.settings.xml site
+
+# upload to maven
+deploy:
+ # as agreed in our SOP, builds on development branch will deploy to our maven repository after validating
+ # the artifact has a proper SNAPSHOT version
+ # artifact will be installed in our testing instance if it is a .war file
+- skip_cleanup: true
+ provider: script
+ script: echo "development deployment" && mvn --quiet --activate-profiles development-build,!release-build --settings .travis.settings.xml deploy
+ on:
+ branch: development
+ condition: '"$TRAVIS_EVENT_TYPE" = "push"'
+ # as agreed in our SOP, tagging a commit on the master branch will upload to our maven repository
+ # after validating the artifact has a proper release version
+ # artifact will be installed in our testing instance if it is a .war file
+- skip_cleanup: true
+ provider: script
+ script: echo "master deployment" && mvn --quiet --activate-profiles !development-build,release-build --settings .travis.settings.xml deploy
+ on:
+ branch: master
+ condition: '"$TRAVIS_EVENT_TYPE" = "push"'
+
+# change according to your needs, but we recommend to deactivate email notifications
+# for now, we configured Travis to send a notification to the #travis-ci channel
+notifications:
+ email:
+ on_success: never
+ on_failure: never
+ slack:
+ on_success: never
+ on_failure: always
+ # edit the following section if you want to get slack notifications
+ rooms:
+ - secure: "***"
+
+# encrypted variables
+env:
+ global:
+ - secure: "LlC638W4guO/Jv8mFTl2ifQG9iFLqkCCjqKrDZkKzWd2KdZBDFygB1dSXVWgORYhzOonfpURiXAiddmKor2w6yO/t9o9MxJ3iN9l6qZCQurNyCb91WhGHKAPy502Ig407rJk8aLPIHgwNVu8PtFJmQFOH5W24YyoVDCjvG5u8hOmNaqdsc7WSkTBThGQsElR16Vm+LA9EbFVBSdhu/QN0slLiqoA2D7MgUFc3Jsxv1PYXrOWUQ5uHZ6VRAdmcYVp1Qt07nuu1QcMr0TEOvCgmyUD8B1FTAuXPYJxLbqvQ8VdgXS99bbbsAC0cxJl/aLjFYeOiJNv79MdG7DM1cbnJwx2pQMvCiFiuukz2NOsffDeR+9M5QbMo3QbjBvzJeQqPm1Ecqk8B7VN0dWpyHlkLzR0qNVOMs6dzfAVpXvLNF7fXf0pZKPE/EzuSxIDLrJtJlKXdyxs0gd8vz2YTtTalwlA6Fr5OZel6pIj3BvphYt4/14PxtNQXL3NDF4r4h0IvjzMYv2SUa2v/hyxORB7P1zgujq8Cf6xG1jz31D5uC3c/g4mOxfY6+b/6Dkbwk5liylOMNNKSknr6IkcfO5NL90BzcE08V7hExci8D1MyMvSNmHnDCxKYySnUeaadOzEXUyZoL5BvMOGi4t2wM1SXvF9K6IKnWu68ooPYNUjeFs="
+ - secure: "AeLiIp7pkGAiokeyTPdVBpVUj1Cp+o/1vWQbvOr4vvOGUJl5hqahRU/A4sWWVb+oPrVbAVt5U/PxPpevTz/27f/rIfYx3jB2YNjgrJ8VE2JfPlBw2bnvnF8YOcimDPmgqHvnNdF319JzdGvv4acucEfbIhj/yfgGsjCi0/7zlDyhJojobyhjF196VsZfxQQNTJCURPbgTU9XciE4JX1dxkpv3Hht/XiJ/WWNUcMsgwWiuVlyeScc64i8giWvpOYmcj11Q0PQFNRwRJ/K4sbRV7GaNhBXTbkmOENGlGapA1MfOQ1726VT/SCzC88DUQLjfVXoOs215VjdSU13B1J6fVN0WJrJcyt6ZjigoaRhrMtFGsuEpegdZGTZn2uo6bJxGY4XPfzy1eshaAx892IfWMC358F+/a89a22v6LmlVQIWtJkos0bQRbvPYMt+eQalwdXAnt4ljL5llxuf7240jAjj0hM2WVRxkgxwIJpfrK7Q4vBGkFQ2Crlrjk3g+TqH4i2zelON5FzhrTSS2N+wu6Zp1+7dhgOm5KSyZTguKmsXKN+gu7BIrVvza0ZDuEQjrgCAZ0kBDtoEAxTdLh3NAf3l2XqkvAlHnsfYA7nJSDkB+Y6mIduRVRsyrr2QazDW6F6jPZzALdNP6BaZbEzbGMCEFnpBeqlJNJtlxNf94sU="
diff --git a/user-db-portlet/CODE_OF_CONDUCT.md b/user-db-portlet/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..8993572
--- /dev/null
+++ b/user-db-portlet/CODE_OF_CONDUCT.md
@@ -0,0 +1,46 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at info@qbic.uni-tuebingen.de. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
+
+[homepage]: http://contributor-covenant.org
+[version]: http://contributor-covenant.org/version/1/4/
diff --git a/user-db-portlet/LICENSE b/user-db-portlet/LICENSE
new file mode 100644
index 0000000..89090ec
--- /dev/null
+++ b/user-db-portlet/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2018, QBiC.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/user-db-portlet/README.md b/user-db-portlet/README.md
new file mode 100644
index 0000000..854d1c0
--- /dev/null
+++ b/user-db-portlet/README.md
@@ -0,0 +1,14 @@
+# User Database Portlet
+
+[](https://travis-ci.com/qbicsoftware/user-db-portlet)[](https://codecov.io/gh/qbicsoftware/user-db-portlet)
+
+User Database Portlet - User DB Tools Portlet enables users to add people and affiliations to the SQL user database.
+
+## Author
+
+Created by Andreas Friedrich (andreas.friedrich@qbic.uni-tuebingen.de).
+
+## Description
+
+## How to Install
+
diff --git a/user-db-portlet/pom.xml b/user-db-portlet/pom.xml
new file mode 100644
index 0000000..87b234b
--- /dev/null
+++ b/user-db-portlet/pom.xml
@@ -0,0 +1,81 @@
+
+
+ 4.0.0
+
+ life.qbic
+ portlet-parent-pom
+ 1.3.0
+
+ user-db-portlet
+ 1.2.0-SNAPSHOT
+ User Database Portlet
+ http://github.com/qbicsoftware/user-db-portlet
+ war
+
+
+
+
+ false
+
+
+ true
+ always
+ fail
+
+ nexus-snapshots
+ QBiC Snapshots
+ https://qbic-repo.am10.uni-tuebingen.de/repository/maven-snapshots
+
+
+
+ true
+ always
+ fail
+
+
+ false
+
+ nexus-releases
+ QBiC Releases
+ https://qbic-repo.am10.uni-tuebingen.de/repository/maven-releases
+
+
+
+
+
+ life.qbic
+ portal-utils-lib
+ 1.3.0
+
+
+ life.qbic
+ openbis-client-lib
+ 1.1.4
+
+
+ life.qbic
+ data-model-lib
+ 1.2.0
+
+
+ org.mariadb.jdbc
+ mariadb-java-client
+
+
+ org.vaadin.addons
+ filteringtable
+ 1.0.0.v7
+
+
+ commons-io
+ commons-io
+ 2.6
+
+
+
diff --git a/user-db-portlet/src/main/java/life/qbic/portal/portlet/ProjectFilterDecorator.java b/user-db-portlet/src/main/java/life/qbic/portal/portlet/ProjectFilterDecorator.java
new file mode 100644
index 0000000..98df63b
--- /dev/null
+++ b/user-db-portlet/src/main/java/life/qbic/portal/portlet/ProjectFilterDecorator.java
@@ -0,0 +1,117 @@
+package life.qbic.portal.portlet;
+
+import java.text.DateFormat;
+import java.util.Locale;
+
+import org.tepi.filtertable.FilterDecorator;
+import org.tepi.filtertable.numberfilter.NumberFilterPopupConfig;
+
+import com.vaadin.server.Resource;
+import com.vaadin.server.ThemeResource;
+import com.vaadin.shared.ui.datefield.Resolution;
+
+public class ProjectFilterDecorator implements FilterDecorator {
+
+ @Override
+ public String getEnumFilterDisplayName(Object propertyId, Object value) {
+ // returning null will output default value
+ return null;
+ }
+
+ @Override
+ public Resource getEnumFilterIcon(Object propertyId, Object value) {
+ return null;
+ }
+
+ @Override
+ public String getBooleanFilterDisplayName(Object propertyId, boolean value) {
+ if ("validated".equals(propertyId)) {
+ return value ? "Validated" : "Not validated";
+ }
+ // returning null will output default value
+ return null;
+ }
+
+ @Override
+ public Resource getBooleanFilterIcon(Object propertyId, boolean value) {
+ if ("validated".equals(propertyId)) {
+ return value ? new ThemeResource("../runo/icons/16/ok.png")
+ : new ThemeResource("../runo/icons/16/cancel.png");
+ }
+ return null;
+ }
+
+ @Override
+ public String getFromCaption() {
+ return "Start date:";
+ }
+
+ @Override
+ public String getToCaption() {
+ return "End date:";
+ }
+
+ @Override
+ public String getSetCaption() {
+ // use default caption
+ return null;
+ }
+
+ @Override
+ public String getClearCaption() {
+ // use default caption
+ return null;
+ }
+
+ @Override
+ public boolean isTextFilterImmediate(Object propertyId) {
+ // use text change events for all the text fields
+ return true;
+ }
+
+ @Override
+ public int getTextChangeTimeout(Object propertyId) {
+ // use the same timeout for all the text fields
+ return 500;
+ }
+
+ @Override
+ public String getAllItemsVisibleString() {
+ return "Show all";
+ }
+
+ @Override
+ public Resolution getDateFieldResolution(Object propertyId) {
+ return Resolution.DAY;
+ }
+
+ public DateFormat getDateFormat(Object propertyId) {
+ return DateFormat.getDateInstance(DateFormat.SHORT, new Locale("fi",
+ "FI"));
+ }
+
+ @Override
+ public boolean usePopupForNumericProperty(Object propertyId) {
+ // TODO Auto-generated method stub
+ return true;
+ }
+
+ @Override
+ public String getDateFormatPattern(Object propertyId) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Locale getLocale() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public NumberFilterPopupConfig getNumberFilterPopupConfig() {
+ // TODO Auto-generated method stub
+ return null;
+}
+
+}
diff --git a/user-db-portlet/src/main/java/life/qbic/portal/portlet/ProjectFilterGenerator.java b/user-db-portlet/src/main/java/life/qbic/portal/portlet/ProjectFilterGenerator.java
new file mode 100644
index 0000000..5934d73
--- /dev/null
+++ b/user-db-portlet/src/main/java/life/qbic/portal/portlet/ProjectFilterGenerator.java
@@ -0,0 +1,72 @@
+package life.qbic.portal.portlet;
+
+import org.tepi.filtertable.FilterGenerator;
+
+import com.vaadin.data.Container.Filter;
+import com.vaadin.data.util.filter.Compare;
+import com.vaadin.data.util.filter.Or;
+import com.vaadin.ui.AbstractField;
+import com.vaadin.ui.CheckBox;
+import com.vaadin.ui.Field;
+
+public class ProjectFilterGenerator implements FilterGenerator {
+
+ @Override
+ public Filter generateFilter(Object propertyId, Object value) {
+ if ("id".equals(propertyId)) {
+ /* Create an 'equals' filter for the ID field */
+ if (value != null && value instanceof String) {
+ try {
+ return new Compare.Equal(propertyId,
+ Integer.parseInt((String) value));
+ } catch (NumberFormatException ignored) {
+ // If no integer was entered, just generate default filter
+ }
+ }
+ } else if ("checked".equals(propertyId)) {
+ if (value != null && value instanceof Boolean) {
+ if (Boolean.TRUE.equals(value)) {
+ return new Compare.Equal(propertyId, value);
+ } else {
+ return new Or(new Compare.Equal(propertyId, true),
+ new Compare.Equal(propertyId, false));
+ }
+ }
+ }
+ // For other properties, use the default filter
+ return null;
+ }
+
+ @Override
+ public Filter generateFilter(Object propertyId, Field> originatingField) {
+ // Use the default filter
+ return null;
+ }
+
+ @Override
+ public AbstractField> getCustomFilterComponent(Object propertyId) {
+ // removed custom filter component for id
+ if ("checked".equals(propertyId)) {
+ CheckBox box = new CheckBox();
+ return box;
+ }
+ return null;
+ }
+
+ @Override
+ public void filterRemoved(Object propertyId) {
+ }
+
+ @Override
+ public void filterAdded(Object propertyId,
+ Class extends Filter> filterType, Object value) {
+ }
+
+ @Override
+ public Filter filterGeneratorFailed(Exception reason, Object propertyId,
+ Object value) {
+ /* Return null -> Does not add any filter on failure */
+ return null;
+}
+
+}
diff --git a/user-db-portlet/src/main/java/life/qbic/portal/portlet/UserDBPortletUI.java b/user-db-portlet/src/main/java/life/qbic/portal/portlet/UserDBPortletUI.java
new file mode 100644
index 0000000..41181e7
--- /dev/null
+++ b/user-db-portlet/src/main/java/life/qbic/portal/portlet/UserDBPortletUI.java
@@ -0,0 +1,596 @@
+package life.qbic.portal.portlet;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.portlet.PortletContext;
+import javax.portlet.PortletSession;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import com.liferay.portal.model.User;
+import com.liferay.portal.model.UserGroup;
+import com.vaadin.annotations.Theme;
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.data.Property.ValueChangeEvent;
+import com.vaadin.data.Property.ValueChangeListener;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.server.WrappedPortletSession;
+import com.vaadin.shared.ui.label.ContentMode;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Layout;
+import com.vaadin.ui.TabSheet;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Experiment;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Project;
+import life.qbic.datamodel.persons.Affiliation;
+import life.qbic.datamodel.persons.CollaboratorWithResponsibility;
+import life.qbic.datamodel.persons.Person;
+import life.qbic.datamodel.projects.ProjectInfo;
+import life.qbic.openbis.openbisclient.IOpenBisClient;
+import life.qbic.openbis.openbisclient.OpenBisClient;
+import life.qbic.openbis.openbisclient.OpenBisClientMock;
+import life.qbic.portal.Styles;
+import life.qbic.portal.Styles.NotificationType;
+import life.qbic.portal.utils.ConfigurationManager;
+import life.qbic.portal.utils.ConfigurationManagerFactory;
+import life.qbic.portal.utils.PortalUtils;
+import life.qbic.userdb.Config;
+import life.qbic.userdb.DBManager;
+import life.qbic.userdb.views.AffiliationInput;
+import life.qbic.userdb.views.AffiliationVIPTab;
+import life.qbic.userdb.views.MultiAffiliationTab;
+import life.qbic.userdb.views.PersonBatchUpload;
+import life.qbic.userdb.views.PersonInput;
+import life.qbic.userdb.views.ProjectView;
+import life.qbic.userdb.views.SearchView;
+
+/**
+ * Entry point for portlet user-db-portlet. This class derives from {@link QBiCPortletUI}, which is
+ * found in the {@code portal-utils-lib} library.
+ */
+@Theme("mytheme")
+@SuppressWarnings("serial")
+@Widgetset("life.qbic.portlet.AppWidgetSet")
+public class UserDBPortletUI extends QBiCPortletUI {
+
+ private static final Logger logger = LogManager.getLogger(UserDBPortletUI.class);
+ private DBManager dbControl;
+ private Map affiMap;
+ private Map personMap;
+
+ private TabSheet options;
+
+ private Config config;
+ public static String tmpFolder;
+
+ private IOpenBisClient openbis;
+ private final boolean testMode = false;
+ private final boolean development = false;
+
+ @Override
+ protected Layout getPortletContent(final VaadinRequest request) {
+ final VerticalLayout layout = new VerticalLayout();
+ layout.setMargin(true);
+ setContent(layout);
+
+ options = new TabSheet();
+
+ this.config = readConfig();
+ tmpFolder = config.getTmpFolder();
+ // LDAPConfig ldapConfig = readLdapConfig();// TODO
+
+ // establish connection to the OpenBIS API
+ if (!development || !testMode) {
+ try {
+ this.openbis = new OpenBisClient(config.getOpenbisUser(), config.getOpenbisPass(),
+ config.getOpenbisURL());
+ this.openbis.login();
+ } catch (Exception e) {
+ // success = false;
+ // logger.error(
+ // "User \"" + userID + "\" could not connect to openBIS and has been informed of this.");
+ // layout.addComponent(new Label(
+ // "Data Management System could not be reached. Please try again later or contact us."));
+ }
+ }
+ if (development && testMode) {
+ logger.error("No connection to openBIS. Trying mock version for testing.");
+ this.openbis = new OpenBisClientMock("", "", "");
+ layout.addComponent(new Label(
+ "openBIS could not be reached. Resuming with mock version. Some options might be non-functional. Reload to retry."));
+ }
+
+ dbControl = new DBManager(config);
+
+ initTabs();
+
+ layout.addComponent(options);
+ return layout;
+ }
+
+
+ private void initTabs() {
+ boolean admin = isAdmin();
+ options.removeAllComponents();
+ if (!admin && !development && !canUsePortlet()) {
+ VerticalLayout rightsMissingTab = new VerticalLayout();
+ rightsMissingTab.setCaption("User Database Input");
+ Label info = new Label(
+ "Your account does not have the necessary rights to add new people to our database.\n"
+ + "If you think you should be able to do so, please contact us.",
+ ContentMode.PREFORMATTED);
+ rightsMissingTab.addComponent(info);
+ options.addTab(rightsMissingTab, "Information");
+ options.setSelectedTab(rightsMissingTab);
+ options.setEnabled(false);
+
+ } else {
+
+ affiMap = dbControl.getAffiliationMap();
+ personMap = dbControl.getPersonMap();
+ Set instituteNames = dbControl.getInstituteNames();
+ List facultyEnums =
+ dbControl.getPossibleEnumsForColumnsInTable("organizations", "faculty");
+ List affiliationRoles =
+ dbControl.getPossibleEnumsForColumnsInTable("persons_organizations", "occupation");
+ List titleEnums = dbControl.getPossibleEnumsForColumnsInTable("persons", "title");
+
+ PersonInput addUserTab = new PersonInput(titleEnums, affiMap, affiliationRoles,
+ new AffiliationInput(instituteNames, facultyEnums, personMap));
+ options.addTab(addUserTab, "New Person");
+
+ AffiliationInput addAffilTab = new AffiliationInput(instituteNames, facultyEnums, personMap);
+ options.addTab(addAffilTab, "New Affiliation");
+
+
+ SearchView searchView = new SearchView();
+ options.addTab(searchView, "Search Entries");
+
+ List affiTable = dbControl.getAffiliationTable();
+ Map> affiPeople = new HashMap>();
+ for (Affiliation a : affiTable) {
+ int id = a.getID();
+ affiPeople.put(id,
+ new ImmutablePair(a.getContactPerson(), a.getHeadName()));
+ }
+
+ PersonBatchUpload batchTab = new PersonBatchUpload(titleEnums, affiliationRoles, affiMap);
+ options.addTab(batchTab, "Upload Person Table");
+
+ AffiliationVIPTab vipTab = new AffiliationVIPTab(personMap, affiMap, affiPeople);
+ options.addTab(vipTab, "Edit Affiliation VIPs");
+
+ MultiAffiliationTab multiAffilTab =
+ new MultiAffiliationTab(personMap, affiMap, affiliationRoles);
+ options.addTab(multiAffilTab, "Additional Person-Affiliations");
+
+ if (!admin) {
+ options.getTab(multiAffilTab).setEnabled(false);
+ options.getTab(vipTab).setEnabled(false);
+
+// options.getTab(3).setEnabled(false);
+// options.getTab(4).setEnabled(false);
+ }
+
+ String userID = "";
+ if (PortalUtils.isLiferayPortlet()) {
+ logger.info("DB Tools running on Liferay, fetching user ID.");
+ userID = PortalUtils.getUser().getScreenName();
+ } else {
+ if (development) {
+ logger.warn("Checks for local dev version successful. User is granted admin status.");
+ userID = "admin";
+ }
+ }
+ Map userProjects = new HashMap();
+
+ List openbisProjects = new ArrayList();
+ if (testMode) {
+ openbisProjects = openbis.listProjects();
+ } else {
+ openbisProjects = openbis.getOpenbisInfoService()
+ .listProjectsOnBehalfOfUser(openbis.getSessionToken(), userID);
+ }
+ Map allProjects = dbControl.getProjectMap();
+ for (Project p : openbisProjects) {
+ String projectID = p.getIdentifier();
+ String code = p.getCode();
+ if (allProjects.get(projectID) == null)
+ userProjects.put(projectID, new ProjectInfo(p.getSpaceCode(), code, "", "", -1));
+ else
+ userProjects.put(projectID, allProjects.get(projectID));
+ }
+
+ ProjectView projectView = new ProjectView(userProjects.values(), openbis, personMap);
+ options.addTab(projectView, "Projects");
+ options.getTab(projectView).setEnabled(!userProjects.isEmpty());
+
+ initPortletToDBFunctionality(addAffilTab, addUserTab, batchTab, multiAffilTab, vipTab,
+ searchView, projectView);
+ }
+ }
+
+ private boolean canUsePortlet() {
+ try {
+ User user = PortalUtils.getUser();
+ for (UserGroup grp : user.getUserGroups()) {
+ String group = grp.getName();
+ if (config.getUserGrps().contains(group)) {
+ logger.info("User " + user.getScreenName() + " can use portlet because they are part of "
+ + group);
+ return true;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ logger.error("Could not fetch user groups. User won't be able to use portlet.");
+ }
+ return false;
+ }
+
+ private boolean isAdmin() {
+ if (development)
+ return true;
+ else {
+ try {
+ User user = PortalUtils.getUser();
+ for (UserGroup grp : user.getUserGroups()) {
+ String group = grp.getName();
+ if (config.getAdminGrps().contains(group)) {
+ logger.info("User " + user.getScreenName()
+ + " has full rights because they are part of " + group);
+ return true;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ logger.error("Could not fetch user groups. User won't be able to use portlet.");
+ }
+ return false;
+ }
+ }
+
+ private void initPortletToDBFunctionality(final AffiliationInput addAffilTab,
+ final PersonInput addUserTab, final PersonBatchUpload batchUpload,
+ final MultiAffiliationTab multiAffilTab, final AffiliationVIPTab vipTab,
+ final SearchView search, final ProjectView projects) {
+
+ batchUpload.getRegisterButton().addClickListener(new Button.ClickListener() {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ *
+ */
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ if (batchUpload.isValid()) {
+ List registered = new ArrayList();
+ batchUpload.setRegEnabled(false);
+ for (Person p : batchUpload.getPeople()) {
+ if (dbControl.personExists(p)) {
+ registered.add(p.getFirstName() + " " + p.getLastName());
+ } else {
+ if (!dbControl.addNewPerson(p)) {
+ commitError("There has been an error while adding a new person.");
+ }
+ }
+ }
+ if (registered.isEmpty())
+ successfulCommit();
+ else {
+ Styles.notification("Person already registered",
+ StringUtils.join(registered, ", ")
+ + " had a username or email already registered in our database! They were skipped in the registration process.",
+ NotificationType.DEFAULT);
+ }
+ }
+ }
+ });
+
+ projects.getProjectTable().addValueChangeListener(new ValueChangeListener() {
+
+ private Map expTypeCodeTranslation = new HashMap() {
+ {
+ put("Q_EXPERIMENTAL_DESIGN", "Patients/Sources");
+ put("Q_SAMPLE_EXTRACTION", "Sample Extracts");
+ put("Q_SAMPLE_PREPARATION", "Sample Preparations");
+ put("Q_MS_MEASUREMENT", "Mass Spectrometry");
+ put("Q_NGS_MEASUREMENT", "NGS Sequencing");
+ };
+ };
+
+ @Override
+ public void valueChange(ValueChangeEvent event) {
+ Object item = projects.getProjectTable().getValue();
+ if (item != null) {
+ String project = item.toString();
+ // get collaborators associated to openbis experiments
+ List collaborators =
+ dbControl.getCollaboratorsOfProject(project);
+ // get openbis experiments and type
+ Map existingExps = new HashMap();
+ for (Experiment e : openbis.getExperimentsForProject2(project)) {
+ String type = expTypeCodeTranslation.get(e.getExperimentTypeCode());
+ String id = e.getIdentifier();
+ if (type != null)
+ existingExps.put(id, type);
+ }
+ // add types for experiments with existing collaborators
+ for (CollaboratorWithResponsibility c : collaborators) {
+ String identifier = c.getOpenbisIdentifier();
+ c.setType(existingExps.get(identifier));
+ existingExps.remove(identifier);
+ }
+ // add empty entries and type for applicable experiments without collaborators
+ for (String expID : existingExps.keySet()) {
+ String code = expID.split("/")[3];
+ CollaboratorWithResponsibility c =
+ new CollaboratorWithResponsibility(-1, "", expID, code, "Contact");
+ c.setType(existingExps.get(expID));
+ collaborators.add(c);
+ }
+ projects.setCollaboratorsOfProject(collaborators);
+ }
+ }
+ });
+
+ projects.getInfoCommitButton().addClickListener(new ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ ProjectInfo info = projects.getEditedInfo();
+ if (info != null) {
+ String code = info.getProjectCode();
+ int id = info.getProjectID();
+ if (id < 1)
+ id = dbControl.addProjectToDB("/" + info.getSpace() + "/" + code,
+ info.getSecondaryName());
+ else
+ dbControl.addOrChangeSecondaryNameForProject(id, info.getSecondaryName());
+ if (info.getInvestigator() == null || info.getInvestigator().isEmpty())
+ dbControl.removePersonFromProject(id, "PI");
+ else
+ dbControl.addOrUpdatePersonToProject(id, personMap.get(info.getInvestigator()), "PI");
+ if (info.getContact() == null || info.getContact().isEmpty())
+ dbControl.removePersonFromProject(id, "Contact");
+ else
+ dbControl.addOrUpdatePersonToProject(id, personMap.get(info.getContact()), "Contact");
+ if (info.getManager() == null || info.getManager().isEmpty())
+ dbControl.removePersonFromProject(id, "Manager");
+ else
+ dbControl.addOrUpdatePersonToProject(id, personMap.get(info.getManager()), "Manager");
+ projects.updateChangedInfo(info);
+ }
+ }
+ });;
+ projects.getPeopleCommitButton().addClickListener(new ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ List links = projects.getNewResponsibilities();
+ for (CollaboratorWithResponsibility c : links) {
+ int experimentID = c.getExperimentID();
+ if (experimentID < 1)
+ experimentID = dbControl.addExperimentToDB(c.getOpenbisIdentifier());
+ String name = c.getPerson();
+ int personID = -1;
+ if (personMap.get(name) != null)
+ personID = personMap.get(name);
+ if (personID < 1)
+ dbControl.removePersonFromExperiment(experimentID);
+ else
+ dbControl.addOrUpdatePersonToExperiment(experimentID, personID, "Contact");
+ }
+ }
+ });;
+
+ search.getSearchAffiliationButton().addClickListener(new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ String affi = search.getAffiliationSearchField().getValue();
+ if (affi != null && !affi.isEmpty()) {
+ search.setAffiliations(dbControl.getAffiliationsContaining(affi));
+ } else
+ search.setAffiliations(new ArrayList());
+ }
+ });
+
+ search.getSearchPersonButton().addClickListener(new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ String person = search.getPersonSearchField().getValue();
+ if (person != null && !person.isEmpty()) {
+ search.setPersons(dbControl.getPersonsContaining(person));
+ } else
+ search.setPersons(new ArrayList());
+ }
+ });
+
+ addAffilTab.getCommitButton().addClickListener(new Button.ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ if (addAffilTab.isValid()) {
+ if (dbControl.addNewAffiliation(addAffilTab.getAffiliation()) > -1)
+ successfulCommit();
+ else
+ commitError("There has been an error.");
+ } else
+ inputError();
+ }
+ });
+
+ vipTab.getSetHeadAndContactButton().addClickListener(new Button.ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ int affi = vipTab.getSelectedAffiTabID();
+ int contact = vipTab.getNewContactID();
+ int head = vipTab.getNewHeadID();
+ if (affi > 0) {
+ if (head > 0)
+ dbControl.setAffiliationVIP(affi, head, "head");
+ if (contact > 0)
+ dbControl.setAffiliationVIP(affi, contact, "main_contact");
+ vipTab.updateVIPs();
+ successfulCommit();
+ }
+ }
+ });
+
+ addAffilTab.getInstituteField().addValueChangeListener(new ValueChangeListener() {
+
+ @Override
+ public void valueChange(ValueChangeEvent event) {
+ Object val = addAffilTab.getInstituteField().getValue();
+ if (val != null) {
+ Affiliation orgInfo = dbControl.getOrganizationInfosFromInstitute(val.toString());
+ if (orgInfo != null)
+ addAffilTab.autoComplete(orgInfo);
+ }
+ }
+ });
+
+ addUserTab.getCommitButton().addClickListener(new Button.ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ if (addUserTab.isValid()) {
+ Person p = addUserTab.getPerson();
+ if (addUserTab.hasNewAffiliation()) {
+ int affiID = dbControl.addNewAffiliation(addUserTab.getNewAffiliation());
+ if (affiID > -1)
+ successfulCommit();
+ else
+ commitError("There has been an error while adding the new affiliation.");
+ p.setAffiliationID(affiID);
+ }
+ if (dbControl.personExists(p)) {
+ Styles.notification("Person already registered",
+ "A person with the Username or E-Mail you selected is already registered in our database!",
+ NotificationType.ERROR);
+ } else {
+ if (dbControl.addNewPerson(p))
+ successfulCommit();
+ else
+ commitError("There has been an error while adding a new person.");
+ }
+ } else
+ inputError();
+ }
+ });
+
+ multiAffilTab.getCommitButton().addClickListener(new Button.ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ if (multiAffilTab.isValid()) {
+ if (dbControl.addOrUpdatePersonAffiliationConnections(
+ personMap.get(multiAffilTab.getPersonBox().getValue()),
+ multiAffilTab.getChangedAndNewConnections()))
+ successfulCommit();
+ else
+ commitError("There has been an error.");
+ } else
+ inputError();
+ }
+ });
+
+ multiAffilTab.getAddButton().addClickListener(new Button.ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ String personName = multiAffilTab.getPersonBox().getValue().toString();
+ Person p = dbControl.getPerson(personMap.get(personName));
+
+ String affiName = multiAffilTab.getOrganizationBox().getValue().toString();
+ Person newP = new Person(p.getUsername(), p.getTitle(), p.getFirstName(), p.getLastName(),
+ p.getEmail(), p.getPhone(), affiMap.get(affiName), affiName, "");
+ multiAffilTab.addDataToTable(new ArrayList(Arrays.asList(newP)));
+ multiAffilTab.getAddButton().setEnabled(false);
+ }
+ });
+
+ ValueChangeListener multiAffiPersonListener = new ValueChangeListener() {
+
+ @Override
+ public void valueChange(ValueChangeEvent event) {
+ if (multiAffilTab.getPersonBox().getValue() != null) {
+ String personName = multiAffilTab.getPersonBox().getValue().toString();
+ multiAffilTab.reactToPersonSelection(
+ dbControl.getPersonWithAffiliations(personMap.get(personName)));
+ multiAffilTab.getAddButton().setEnabled(multiAffilTab.newAffiliationPossible());
+ }
+ }
+ };
+ multiAffilTab.getPersonBox().addValueChangeListener(multiAffiPersonListener);
+
+ ValueChangeListener multiAffiListener = new ValueChangeListener() {
+
+ @Override
+ public void valueChange(ValueChangeEvent event) {
+ if (multiAffilTab.getPersonBox().getValue() != null) {
+ multiAffilTab.getAddButton().setEnabled(multiAffilTab.newAffiliationPossible());
+ }
+ }
+ };
+ multiAffilTab.getOrganizationBox().addValueChangeListener(multiAffiListener);
+ }
+
+ private void successfulCommit() {
+ Styles.notification("Data added", "Data has been successfully added to the database!",
+ NotificationType.SUCCESS);
+ // wait a bit and reload tabs
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ initTabs();
+ }
+
+ private void inputError() {
+ Styles.notification("Data Incomplete", "Please fill in all required fields correctly.",
+ NotificationType.DEFAULT);
+ }
+
+ private void commitError(String reason) {
+ Styles.notification("There has been an error.", reason, NotificationType.ERROR);
+ }
+
+ private Config readConfig() {
+ ConfigurationManager c = ConfigurationManagerFactory.getInstance();
+
+ return new Config(c.getMysqlHost(), c.getMysqlPort(), c.getMysqlDB(), c.getMysqlUser(),
+ c.getMysqlPass(), c.getUserDBInputUserGrps(), c.getUserDBInputAdminGrps(), c.getDataSourceUrl(),
+ c.getDataSourceUser(), c.getDataSourcePassword(), c.getTmpFolder());
+ }
+
+ private String getPortletContextName(VaadinRequest request) {
+ WrappedPortletSession wrappedPortletSession =
+ (WrappedPortletSession) request.getWrappedSession();
+ PortletSession portletSession = wrappedPortletSession.getPortletSession();
+
+ final PortletContext context = portletSession.getPortletContext();
+ final String portletContextName = context.getPortletContextName();
+ return portletContextName;
+ }
+}
diff --git a/user-db-portlet/src/main/java/life/qbic/userdb/Config.java b/user-db-portlet/src/main/java/life/qbic/userdb/Config.java
new file mode 100644
index 0000000..92dc767
--- /dev/null
+++ b/user-db-portlet/src/main/java/life/qbic/userdb/Config.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * QBiC User DB Tools enables users to add people and affiliations to our mysql user database.
+ * Copyright (C) 2016 Andreas Friedrich
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ *******************************************************************************/
+package life.qbic.userdb;
+
+import java.util.List;
+
+public class Config {
+
+ private String hostname;
+ private String port;
+ private String sql_database;
+ private String username;
+ private String password;
+ private String openbisURL;
+ private String openbisUser;
+ private String openbisPass;
+ private List userGrps;
+ private List adminGrps;
+ private String tmpFolder;
+
+ public Config(String hostname, String port, String sql_database, String username, String password,
+ List userGrps, List adminGrps, String openbisURL, String openbisUser,
+ String openbisPass, String tmpFolder) {
+ this.hostname = hostname;
+ this.port = port;
+ this.sql_database = sql_database;
+ this.username = username;
+ this.password = password;
+ this.adminGrps = adminGrps;
+ this.userGrps = userGrps;
+ this.openbisURL = openbisURL;
+ this.openbisUser = openbisUser;
+ this.openbisPass = openbisPass;
+ this.tmpFolder = tmpFolder;
+ }
+
+ public String getTmpFolder() {
+ return tmpFolder;
+ }
+
+ public String getOpenbisURL() {
+ return openbisURL;
+ }
+
+ public String getOpenbisUser() {
+ return openbisUser;
+ }
+
+ public String getOpenbisPass() {
+ return openbisPass;
+ }
+
+ public List getUserGrps() {
+ return userGrps;
+ }
+
+ public List getAdminGrps() {
+ return adminGrps;
+ }
+
+ public String getHostname() {
+ return hostname;
+ }
+
+ public String getPort() {
+ return port;
+ }
+
+ public String getSql_database() {
+ return sql_database;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+
+
+}
diff --git a/user-db-portlet/src/main/java/life/qbic/userdb/DBManager.java b/user-db-portlet/src/main/java/life/qbic/userdb/DBManager.java
new file mode 100644
index 0000000..b5d6d9e
--- /dev/null
+++ b/user-db-portlet/src/main/java/life/qbic/userdb/DBManager.java
@@ -0,0 +1,1814 @@
+/*******************************************************************************
+ * QBiC User DB Tools enables users to add people and affiliations to our mysql user database.
+ * Copyright (C) 2016 Andreas Friedrich
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ *******************************************************************************/
+package life.qbic.userdb;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import life.qbic.datamodel.persons.Affiliation;
+import life.qbic.datamodel.persons.CollaboratorWithResponsibility;
+import life.qbic.datamodel.persons.Person;
+import life.qbic.datamodel.persons.PersonAffiliationConnectionInfo;
+import life.qbic.datamodel.persons.RoleAt;
+import life.qbic.datamodel.projects.ProjectInfo;
+import life.qbic.userdb.model.Minutes;
+
+public class DBManager {
+ private Config config;
+
+ Logger logger = LogManager.getLogger(DBManager.class);
+
+ public DBManager(Config config) {
+ this.config = config;
+ }
+
+ private void logout(Connection conn) {
+ try {
+ conn.close();
+ } catch (SQLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ private void printAffiliations() {
+ String sql = "SELECT * FROM organizations";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ ResultSet rs = statement.executeQuery();
+ while (rs.next()) {
+ logger.info(Integer.toString(rs.getInt(1)) + " " + rs.getString(2) + " "
+ + rs.getString(3) + " " + rs.getString(4) + " " + rs.getString(5) + " "
+ + rs.getString(6) + " " + rs.getString(7) + " " + rs.getString(8) + " "
+ + rs.getString(9) + " " + rs.getString(10) + " " + rs.getString(11));
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ }
+
+ public String getProjectName(String projectIdentifier) {
+ String sql = "SELECT short_title from projects WHERE openbis_project_identifier = ?";
+ String res = "";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setString(1, projectIdentifier);
+ ResultSet rs = statement.executeQuery();
+ if (rs.next()) {
+ res = rs.getString(1);
+ }
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res;
+ }
+
+ private void removePersonFromAllProjects(int userID) {
+ logger.info("Trying to remove all project associations of user with ID " + userID);
+ String sql = "DELETE FROM projects_persons WHERE person_id = ?";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setInt(1, userID);
+ statement.execute();
+ logger.info("Successful.");
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ }
+
+ private void removePersonFromAllAffiliationRoles(int userID) {
+ logger.info("Trying to remove all affiliation associations of user with ID " + userID);
+ String sql = "DELETE FROM persons_organizations WHERE person_id = ?";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setInt(1, userID);
+ statement.execute();
+ logger.info("Successful.");
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ endQuery(null, statement);
+ }
+ logger.info("Trying to remove user from special affiliation roles");
+ sql = "UPDATE organizations SET head=NULL WHERE head = ?";
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setInt(1, userID);
+ statement.execute();
+ logger.info("Successful for head.");
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ endQuery(null, statement);
+ }
+
+ sql = "UPDATE organizations SET main_contact=NULL WHERE main_contact = ?";
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setInt(1, userID);
+ statement.execute();
+ logger.info("Successful for main contact.");
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ }
+
+ private Connection login() {
+ String DB_URL = "jdbc:mariadb://" + config.getHostname() + ":" + config.getPort() + "/"
+ + config.getSql_database();
+ Connection conn = null;
+ try {
+ Class.forName("org.mariadb.jdbc.Driver");
+ conn = DriverManager.getConnection(DB_URL, config.getUsername(), config.getPassword());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return conn;
+ }
+
+ public void addOrChangeSecondaryNameForProject(int projectID, String secondaryName) {
+ logger.info(
+ "Adding/Updating secondary name of project with id " + projectID + " to " + secondaryName);
+ boolean saved = saveOldSecondaryNameForProjects(projectID);
+ if (!saved)
+ logger.warn("Could not save old project description to database!");
+ String sql = "UPDATE projects SET short_title = ? WHERE id = ?";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setString(1, secondaryName);
+ statement.setInt(2, projectID);
+ statement.execute();
+ logger.info("Successful.");
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ }
+
+ private boolean saveOldSecondaryNameForProjects(int id) {
+ String sql = "SELECT * from projects WHERE id = ?";
+ String oldDescription = "";
+ String oldTitle = "";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setInt(1, id);
+ ResultSet rs = statement.executeQuery();
+ if (rs.next()) {
+ oldDescription = rs.getString("long_description");
+ oldTitle = rs.getString("short_title");
+ }
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ }
+ Date date = new java.util.Date();
+ Timestamp timestamp = new Timestamp(date.getTime());
+ sql =
+ "INSERT INTO projects_history (project_id, timestamp, long_description, short_title) VALUES(?, ?, ?, ?)";
+ statement = null;
+ int res = -1;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setInt(1, id);
+ statement.setTimestamp(2, timestamp);
+ statement.setString(3, oldDescription);
+ statement.setString(4, oldTitle);
+ statement.execute();
+ res = statement.getUpdateCount();
+ logger.info("Successful.");
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res != -1;
+ }
+
+ public int addMinutes(Minutes m) {
+ logger.info("Adding minutes information.");
+ String sql = "INSERT into project_minutes values (? ? ? ? ? ?)";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setString(1, m.getPurpose());
+ statement.setString(2, m.getParticipants());
+ statement.setString(3, m.getAgenda());
+ statement.setString(4, m.getDiscussion());
+ statement.setString(5, m.getResults());
+ statement.setString(6, m.getNextSteps());
+ statement.execute();
+ ResultSet rs = statement.getGeneratedKeys();
+ if (rs.next()) {
+ logout(conn);
+ logger.info("Successful.");
+ return rs.getInt(1);
+ }
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return -1;
+ }
+
+ public Minutes getMinutesByID(int id) {
+ logger.info("Looking for project minutes with id " + id + ".");
+ String sql = "SELECT * from project_minutes WHERE id = ?";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setInt(1, id);
+ ResultSet rs = statement.executeQuery();
+ while (rs.next()) {
+ return new Minutes(id, rs.getString("purpose"), rs.getString("participants"),
+ rs.getString("agenda"), rs.getString("discussion"), rs.getString("results"),
+ rs.getString("next_steps"));
+ }
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return null;
+ }
+
+ public List getPossibleEnumsForColumnsInTable(String table, String column) {
+ String sql = "desc " + table + " " + column;
+ Connection conn = login();
+ List res = new ArrayList();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ ResultSet rs = statement.executeQuery();
+ while (rs.next()) {
+ for (String s : rs.getString(2).replace("enum('", "").replace("')", "").split("','"))
+ res.add(s);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res;
+ }
+
+ public List getPossibleSetOptionsForColumnsInTable(String table, String column) {
+ String sql = "desc " + table + " " + column;
+ Connection conn = login();
+ List res = new ArrayList();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ ResultSet rs = statement.executeQuery();
+ while (rs.next()) {
+ for (String s : rs.getString(2).replace("set('", "").replace("')", "").split("','"))
+ res.add(s);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res;
+ }
+
+ public boolean isProjectInDB(String projectIdentifier) {
+ logger.info("Looking for project " + projectIdentifier + " in the DB");
+ String sql = "SELECT * from projects WHERE openbis_project_identifier = ?";
+ boolean res = false;
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setString(1, projectIdentifier);
+ ResultSet rs = statement.executeQuery();
+ if (rs.next()) {
+ res = true;
+ logger.info("project found!");
+ }
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res;
+ }
+
+ public int addProjectToDB(String projectIdentifier, String projectName) {
+ if (!isProjectInDB(projectIdentifier)) {
+ logger.info("Trying to add project " + projectIdentifier + " to the person DB");
+ String sql = "INSERT INTO projects (openbis_project_identifier, short_title) VALUES(?, ?)";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
+ statement.setString(1, projectIdentifier);
+ statement.setString(2, projectName);
+ statement.execute();
+ ResultSet rs = statement.getGeneratedKeys();
+ if (rs.next()) {
+ logout(conn);
+ logger.info("Successful.");
+ return rs.getInt(1);
+ }
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return -1;
+ }
+ return -1;
+ }
+
+ public boolean hasPersonRoleInProject(int personID, int projectID, String role) {
+ logger.info("Checking if person already has this role in the project.");
+ String sql =
+ "SELECT * from projects_persons WHERE person_id = ? AND project_id = ? and project_role = ?";
+ boolean res = false;
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setInt(1, personID);
+ statement.setInt(2, projectID);
+ statement.setString(3, role);
+ ResultSet rs = statement.executeQuery();
+ if (rs.next()) {
+ res = true;
+ logger.info("person already has this role!");
+ }
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res;
+ }
+
+ public void addOrUpdatePersonToProject(int projectID, int personID, String role) {
+ if (!hasPersonRoleInProject(personID, projectID, role)) {
+ logger.info("Trying to add person with role " + role + " to a project.");
+ if (!roleForProjectTaken(projectID, role)) {
+ logger.info("Role " + role + " is not yet taken.");
+ String sql =
+ "INSERT INTO projects_persons (project_id, person_id, project_role) VALUES(?, ?, ?)";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
+ statement.setInt(1, projectID);
+ statement.setInt(2, personID);
+ statement.setString(3, role);
+ statement.execute();
+ logger.info("Successful.");
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ } else {
+ logger.info("Role " + role + " is taken. Updating to new person.");
+ String sql =
+ "UPDATE projects_persons SET person_id = ? WHERE project_id = ? AND project_role = ?;";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
+ statement.setInt(1, personID);
+ statement.setInt(2, projectID);
+ statement.setString(3, role);
+ statement.execute();
+ logger.info("Successful.");
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ }
+ }
+ }
+
+ private boolean roleForProjectTaken(int projectID, String role) {
+ boolean res = false;
+ String sql = "SELECT person_ID FROM projects_persons WHERE project_id = ? AND project_role = ?";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setInt(1, projectID);
+ statement.setString(2, role);
+ ResultSet rs = statement.executeQuery();
+ while (rs.next()) {
+ res = true;
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res;
+ }
+
+ private boolean roleForExperimentTaken(int experimentID, String role) {
+ boolean res = false;
+ String sql =
+ "SELECT person_ID FROM experiments_persons WHERE experiment_id = ? AND experiment_role = ?";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setInt(1, experimentID);
+ statement.setString(2, role);
+ ResultSet rs = statement.executeQuery();
+ while (rs.next()) {
+ res = true;
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res;
+ }
+
+ public void printPeople() {
+ String sql = "SELECT * FROM project_investigators";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ ResultSet rs = statement.executeQuery();
+ while (rs.next()) {
+ logger.info(Integer.toString(rs.getInt(1)) + " " + rs.getString(2) + " "
+ + rs.getString(3) + " " + rs.getString(4) + " " + rs.getString(5) + " "
+ + rs.getString(6) + " " + rs.getString(7) + " " + rs.getString(8) + " "
+ + rs.getString(9) + " " + rs.getString(10) + " " + rs.getString(11));
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ }
+
+ public void printProjects() {
+ String sql = "SELECT pi_id, project_code FROM projects";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ ResultSet rs = statement.executeQuery();
+ while (rs.next()) {
+ int pi_id = rs.getInt("pi_id");
+ String first = rs.getString("project_code");
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ }
+
+ public Map getAffiliationMap() {
+ Map res = new HashMap();
+ String sql = "SELECT * FROM organizations";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ ResultSet rs = statement.executeQuery();
+ while (rs.next()) {
+ int id = rs.getInt("id");
+ String groupName = rs.getString("group_name");
+ String acronym = rs.getString("group_acronym");
+ String organization = rs.getString("institute");
+
+ String resName = "";
+ boolean group = !(groupName == null || groupName.isEmpty());
+ boolean acr = !(acronym == null || acronym.isEmpty());
+ boolean org = !(organization == null || organization.isEmpty());
+
+ // no group
+ if (!group) {
+ // no acronym
+ if (!acr) {
+ // no org
+ if (!org) {
+ resName = "unknown";
+ } else {
+ resName = organization;
+ }
+ // acronym
+ } else {
+ // no org
+ if (!org) {
+ resName = acronym;
+ } else {
+ resName = acronym + " - " + organization;
+ }
+ }
+ // group
+ } else {
+ // no acronym
+ if (!acr) {
+ // no org
+ if (!org) {
+ resName = groupName;
+ } else {
+ resName = groupName + " - " + organization;
+ }
+ // acronym
+ } else {
+ // no org
+ if (!org) {
+ resName = groupName + " (" + acronym + ")";
+ } else {
+ resName = groupName + " (" + acronym + ") - " + organization;
+ }
+ }
+ }
+
+ res.put(resName, id);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res;
+ }
+
+ public int addNewAffiliation(Affiliation affiliation) {
+ int res = -1;
+ logger.info("Trying to add new affiliation to the DB");
+ // TODO empty values are inserted as empty strings, ok?
+ String insert =
+ "INSERT INTO organizations (group_name,group_acronym,umbrella_organization,institute,faculty,street,zip_code,"
+ + "city,country,webpage";
+ String values = "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?";
+ if (affiliation.getContactPersonID() > 0) {
+ insert += ",main_contact";
+ values += ", ?";
+ }
+ if (affiliation.getHeadID() > 0) {
+ insert += ",head";
+ values += ", ?";
+ }
+ String sql = insert + ") " + values + ")";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
+ statement.setString(1, affiliation.getGroupName());
+ statement.setString(2, affiliation.getAcronym());
+ statement.setString(3, affiliation.getOrganization());
+ statement.setString(4, affiliation.getInstitute());
+ statement.setString(5, affiliation.getFaculty());
+ statement.setString(6, affiliation.getStreet());
+ statement.setString(7, affiliation.getZipCode());
+ statement.setString(8, affiliation.getCity());
+ statement.setString(9, affiliation.getCountry());
+ statement.setString(10, affiliation.getWebpage());
+ int offset = 0;
+ if (affiliation.getContactPersonID() > 0) {
+ statement.setInt(11, affiliation.getContactPersonID());
+ offset++;
+ }
+ if (affiliation.getHeadID() > 0)
+ statement.setInt(11 + offset, affiliation.getHeadID());
+ statement.execute();
+ ResultSet rs = statement.getGeneratedKeys();
+ if (rs.next()) {
+ logout(conn);
+ logger.info("Successful.");
+ res = rs.getInt(1);
+ }
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res;
+ }
+
+ private String getFreeDummyUserName() {
+ List existing = getPeopleWithDummyUserNames();
+ int last = 0;
+ for (Person p : existing) {
+ String user = p.getUsername();
+ try {
+ int num = Integer.parseInt(user.substring(4));
+ last = Math.max(last, num);
+ } catch (NumberFormatException e) {
+ logger.warn("Could not parse number from dummy username " + user);
+ }
+ }
+ return "todo" + Integer.toString(last + 1);
+
+ }
+
+ public List getPeopleWithDummyUserNames() {
+ String dummy = "todo";
+ List existing = new ArrayList();
+ String sql = "SELECT * FROM persons WHERE username LIKE ?";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setString(1, dummy + "%");
+ ResultSet rs = statement.executeQuery();
+ while (rs.next()) {
+ String username = rs.getString("username");
+ String title = rs.getString("title");
+ String first = rs.getString("first_name");
+ String last = rs.getString("family_name");
+ String email = rs.getString("email");
+ String phone = rs.getString("phone");
+ existing.add(new Person(username, title, first, last, email, phone, -1, "", ""));
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return existing;
+ }
+
+ public boolean addNewPerson(Person person) {
+ logger.info("Trying to add new person to the DB");
+ // TODO empty values are inserted as empty strings, ok?
+ boolean res = false;
+ String sql =
+ "INSERT INTO persons (username,title,first_name,family_name,email,phone,active) VALUES(?, ?, ?, ?, ?, ?, ?)";
+ Connection conn = login();
+ int person_id = -1;
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
+ String user = person.getUsername();
+ if (user == null || user.isEmpty())
+ user = getFreeDummyUserName();
+ statement.setString(1, user);
+ statement.setString(2, person.getTitle());
+ statement.setString(3, person.getFirstName());
+ statement.setString(4, person.getLastName());
+ statement.setString(5, person.getEmail());
+ statement.setString(6, person.getPhone());
+ statement.setBoolean(7, true);
+ statement.execute();
+ ResultSet answer = statement.getGeneratedKeys();
+ answer.next();
+ person_id = answer.getInt(1);
+ res = true;
+ logger.info("Successfully added person to db.");
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ if (statement != null)
+ endQuery(null, statement);
+ }
+ if (person_id > 0) {
+ Map affiliationInfos = person.getAffiliationInfos();
+ for (int affiliation_id : affiliationInfos.keySet()) {
+ sql =
+ "INSERT INTO persons_organizations (person_id, organization_id, occupation) VALUES(?, ?, ?)";
+ try {
+ statement = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
+ statement.setInt(1, person_id);
+ statement.setInt(2, affiliation_id);
+ statement.setString(3, affiliationInfos.get(affiliation_id).getRole());
+ statement.execute();
+ logger.info("Successfully added person affiliation information to db.");
+ } catch (SQLException e) {
+ res = false;
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ endQuery(null, statement);
+ }
+ }
+ }
+ if (conn != null)
+ logout(conn);
+ return res;
+ }
+
+ // public List getPersons() {
+ // List res = new ArrayList();
+ // String sql = "SELECT * FROM person";
+ // Connection conn = login();
+ // try (PreparedStatement statement = conn.prepareStatement(sql)) {
+ // ResultSet rs = statement.executeQuery();
+ // while (rs.next()) {
+ // String first = Integer.toString(rs.getInt("first_name"));
+ // String last = Integer.toString(rs.getInt("last_name"));
+ // res.add(first + " " + last);
+ // }
+ // } catch (SQLException e) {
+ // e.printStackTrace();
+ // } finally {
+ // endQuery(conn, statement);
+ // }
+ // return res;
+ // }
+
+ public Map getPersonMap() {
+ Map res = new HashMap();
+ String sql = "SELECT * FROM persons";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ ResultSet rs = statement.executeQuery();
+ while (rs.next()) {
+ int id = rs.getInt("id");
+ String first = rs.getString("first_name");
+ String last = rs.getString("family_name");
+ res.put(first + " " + last, id);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res;
+ }
+
+ public void printTableNames() throws SQLException {
+ Connection conn = login();
+ DatabaseMetaData md = conn.getMetaData();
+ ResultSet rs = md.getTables(null, null, "%", null);
+ while (rs.next()) {
+ String table = rs.getString(3);
+ logger.info(table);
+ String sql = "SELECT * FROM " + table;
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ ResultSet r = statement.executeQuery();
+ ResultSetMetaData metaData = r.getMetaData();
+ int count = metaData.getColumnCount(); // number of column
+ for (int i = 1; i <= count; i++) {
+ logger.info("col: " + metaData.getColumnLabel(i));
+ }
+ } catch (Exception e) {
+ // TODO: handle exception
+ } finally {
+ if (statement != null)
+ statement.close();
+ }
+ }
+ logout(conn);
+ }
+
+ public boolean addOrUpdatePersonAffiliationConnections(int personID,
+ List newConnections) {
+ Connection conn = login();
+ boolean res = false;
+ String sql = "";
+ PreparedStatement statement = null;
+ List knownAffiliationIDs = getPersonAffiliationIDs(personID);
+ for (PersonAffiliationConnectionInfo data : newConnections) {
+ int affiID = data.getAffiliation_id();
+ String role = data.getRole();
+ logger.debug("Trying to add user " + personID + " (" + role + ") to affiliation " + affiID);
+ if (knownAffiliationIDs.contains(affiID)) {
+ logger.debug("user is part of that affiliation, updating role");
+ sql =
+ "UPDATE persons_organizations SET occupation = ? WHERE person_id = ? and organization_id = ?";
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setInt(2, personID);
+ statement.setInt(3, affiID);
+ statement.setString(1, role);
+ statement.execute();
+ logger.info("Successful.");
+ res = true;
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ // we updated this connection and can remove the id
+ knownAffiliationIDs.remove(new Integer(affiID));
+ }
+ } else {
+ sql =
+ "INSERT INTO persons_organizations (person_id, organization_id, occupation) VALUES (?,?,?)";
+ try {
+ logger.debug("user is not part of that affiliation yet, inserting");
+ statement = conn.prepareStatement(sql);
+ statement.setInt(1, personID);
+ statement.setInt(2, affiID);
+ statement.setString(3, role);
+ statement.execute();
+ logger.info("Successful.");
+ res = true;
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ // we added this connection and can remove the id
+ knownAffiliationIDs.remove(new Integer(affiID));
+ }
+ }
+ }
+ // any ID still in the list must be from an affiliation connection that the user removed in
+ // the UI, thus we remove it from the DB
+ for (int oldAffiID : knownAffiliationIDs) {
+ sql = "DELETE FROM persons_organizations WHERE person_id = ? and organization_id = ?";
+ try {
+ logger.debug("user affiliation id " + oldAffiID
+ + " found in DB, but not in updated connections, deleting this connection");
+ statement = conn.prepareStatement(sql);
+ statement.setInt(1, personID);
+ statement.setInt(2, oldAffiID);
+ statement.execute();
+ logger.info("Successful.");
+ res = true;
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+ endQuery(conn, statement);
+ return res;
+ }
+
+ public List getPersonAffiliationIDs(int person_id) {
+ List res = new ArrayList();
+ String sql = "SELECT * FROM persons_organizations WHERE person_id = ?";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setInt(1, person_id);
+ ResultSet rs = statement.executeQuery();
+ while (rs.next()) {
+ res.add(rs.getInt("organization_id"));
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res;
+ }
+
+ public List getPersonTable() {
+ List res = new ArrayList();
+ String lnk = "persons_organizations";
+ String sql =
+ "SELECT persons.*, organizations.id, organizations.group_name, organizations.group_acronym, "
+ + lnk + ".occupation FROM persons, organizations, " + lnk + " WHERE persons.id = " + lnk
+ + ".person_id and organizations.id = " + lnk + ".organization_id";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ ResultSet rs = statement.executeQuery();
+ while (rs.next()) {
+ int id = rs.getInt("id");
+ String username = rs.getString("username");
+ String title = rs.getString("title");
+ String first = rs.getString("first_name");
+ String last = rs.getString("family_name");
+ String eMail = rs.getString("email");
+ String phone = rs.getString("phone");
+ int affiliationID = rs.getInt("organizations.id");
+ String affiliation =
+ rs.getString("group_name") + " (" + rs.getString("group_acronym") + ")";
+ String role = rs.getString(lnk + ".occupation");
+ res.add(new Person(username, title, first, last, eMail, phone, affiliationID, affiliation,
+ role)); // TODO add every affiliation!
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res;
+ }
+
+ public Set getInstituteNames() {
+ Set res = new HashSet();
+ String sql = "SELECT institute FROM organizations";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ ResultSet rs = statement.executeQuery();
+ while (rs.next()) {
+ String inst = rs.getString("institute");
+ if (inst != null)
+ res.add(inst);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res;
+ }
+
+ public Affiliation getOrganizationInfosFromInstitute(String institute) {
+ Affiliation res = null;
+ String sql = "SELECT * FROM organizations WHERE institute LIKE ?";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setString(1, institute + "%");
+ ResultSet rs = statement.executeQuery();
+ Set streets = new HashSet();
+ Set orgs = new HashSet();
+ Set faculties = new HashSet();
+ Set zips = new HashSet();
+ Set cities = new HashSet();
+ Set countries = new HashSet();
+ while (rs.next()) {
+ faculties.add(rs.getString("faculty"));
+ orgs.add(rs.getString("umbrella_organization"));
+ streets.add(rs.getString("street"));
+ zips.add(rs.getInt("zip_code"));
+ countries.add(rs.getString("country"));
+ cities.add(rs.getString("city"));
+ institute = rs.getString("institute");
+ }
+ String street = "";
+ String faculty = "";
+ String organization = "";
+ String zipCode = "";
+ String city = "";
+ String country = "";
+ if (streets.size() == 1)
+ street = streets.iterator().next();
+ if (orgs.size() == 1)
+ organization = orgs.iterator().next();
+ if (faculties.size() == 1)
+ faculty = faculties.iterator().next();
+ if (countries.size() == 1)
+ country = countries.iterator().next();
+ if (zips.size() == 1)
+ zipCode = Integer.toString(zips.iterator().next());
+ if (cities.size() == 1)
+ city = cities.iterator().next();
+ res = new Affiliation(-1, "", "", organization, institute, faculty, "", "", street, zipCode,
+ city, country, "");
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res;
+ }
+
+ public Affiliation getOrganizationInfosFromOrg(String organization) {
+ Affiliation res = null, maybe = null;
+ String sql = "SELECT * FROM organizations WHERE umbrella_organization LIKE ?";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setString(1, organization + "%");
+ ResultSet rs = statement.executeQuery();
+ String street = "";
+ while (rs.next()) {
+ String faculty = rs.getString("faculty");
+ String institute = rs.getString("institute");
+ if (!street.isEmpty() && !street.equals(rs.getString("street"))) {
+ street = "";
+ break;
+ } else
+ street = rs.getString("street");
+ organization = rs.getString("umbrella_organization");
+ String zipCode = rs.getString("zip_code");
+ String city = rs.getString("city");
+ String country = rs.getString("country");
+ maybe = new Affiliation(-1, "", "", organization, institute, faculty, "", "", street,
+ zipCode, city, country, "");
+ }
+ if (!street.isEmpty())
+ res = maybe;
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res;
+ }
+
+ public List getAffiliationTable() {
+ List res = new ArrayList();
+ String sql = "SELECT * from organizations";
+ // String sql =
+ // "SELECT organizations.*, persons.first_name, persons.family_name FROM organizations, persons"
+ // + " WHERE persons.id = main_contact";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ ResultSet rs = statement.executeQuery();
+ while (rs.next()) {
+ int id = rs.getInt("id");
+ String groupName = rs.getString("group_name");
+ String acronym = rs.getString("group_acronym");
+ if (acronym == null)
+ acronym = "";
+ String organization = rs.getString("umbrella_organization");
+ String faculty = rs.getString("faculty");
+ String institute = rs.getString("institute");
+ if (institute == null)
+ institute = "";
+ String street = rs.getString("street");
+ String zipCode = rs.getString("zip_code");
+ String city = rs.getString("city");
+ String country = rs.getString("country");
+ String webpage = rs.getString("webpage");
+ int contactID = rs.getInt("main_contact");
+ int headID = rs.getInt("head");
+ String contact = null;
+ String head = null;
+ if (contactID > 0) {
+ Person c = getPerson(contactID);
+ contact = c.getFirstName() + " " + c.getLastName();
+ }
+ if (headID > 0) {
+ Person h = getPerson(headID);
+ head = h.getFirstName() + " " + h.getLastName();
+ }
+ res.add(new Affiliation(id, groupName, acronym, organization, institute, faculty, contact,
+ head, street, zipCode, city, country, webpage));
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res;
+ }
+
+
+ public String getInvestigatorForProject(String projectIdentifier) {
+ String details = getPersonDetailsForProject(projectIdentifier, "PI");
+ return details.split("\n")[0].trim();
+ }
+
+ public String getPersonDetailsForProject(String projectIdentifier, String role) {
+ String sql =
+ "SELECT projects_persons.*, projects.* FROM projects_persons, projects WHERE projects.openbis_project_identifier = ?"
+ + " AND projects.id = projects_persons.project_id AND projects_persons.project_role = ?";
+
+ int id = -1;
+
+ List personWithAffiliations = new ArrayList();
+
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setString(1, projectIdentifier);
+ statement.setString(2, role);
+
+ ResultSet rs = statement.executeQuery();
+
+ while (rs.next()) {
+ id = rs.getInt("person_id");
+ }
+ personWithAffiliations = getPersonWithAffiliations(id);
+ } catch (SQLException e) {
+ e.printStackTrace();
+ logout(conn);
+ // LOGGER.debug("Project not associated with Investigator. PI will be set to 'Unknown'");
+ } finally {
+ endQuery(conn, statement);
+ }
+
+ String details = "";
+ if (personWithAffiliations.size() > 0) {
+ Person p = personWithAffiliations.get(0);
+ String institute = p.getOneAffiliationWithRole().getAffiliation();
+
+ details = String.format("%s %s \n%s \n \n%s \n%s \n", p.getFirstName(), p.getLastName(),
+ institute, p.getPhone(), p.getEmail());
+ // TODO is address important?
+ }
+ return details;
+ }
+
+ /**
+ * returns multiple person objects if they have multiple affiliations
+ *
+ * @param personID
+ * @return
+ */
+ public List getPersonWithAffiliations(Integer personID) {
+ List res = new ArrayList();
+ String lnk = "persons_organizations";
+ String sql =
+ "SELECT persons.*, organizations.id, organizations.group_name, organizations.group_acronym, "
+ + lnk + ".occupation FROM persons, organizations, " + lnk + " WHERE persons.id = "
+ + Integer.toString(personID) + " AND persons.id = " + lnk
+ + ".person_id and organizations.id = " + lnk + ".organization_id";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ ResultSet rs = statement.executeQuery();
+ List affiliations = new ArrayList();
+ while (rs.next()) {
+ affiliations.add(getAffiliationWithID(rs.getInt("organizations.id")));
+ int id = rs.getInt("id");
+ String username = rs.getString("username");
+ String title = rs.getString("title");
+ String first = rs.getString("first_name");
+ String last = rs.getString("family_name");
+ String eMail = rs.getString("email");
+ String phone = rs.getString("phone");
+ int affiliationID = rs.getInt("organizations.id");
+ String affiliation = rs.getString("group_name");
+ String acr = rs.getString("group_acronym");
+ if (acr != null && !acr.isEmpty()) {
+ affiliation += " (" + rs.getString("group_acronym") + ")";
+ }
+ String role = rs.getString(lnk + ".occupation");
+ res.add(new Person(username, title, first, last, eMail, phone, affiliationID, affiliation,
+ role, affiliations));
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res;
+ }
+
+ private Affiliation getAffiliationWithID(int id) {
+ Affiliation res = null;
+ String sql = "SELECT * from organizations WHERE id = ?";
+
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setInt(1, id);
+ ResultSet rs = statement.executeQuery();
+ while (rs.next()) {
+ String groupName = rs.getString("group_name");
+ String acronym = rs.getString("group_acronym");
+ if (acronym == null)
+ acronym = "";
+ String organization = rs.getString("umbrella_organization");
+ String faculty = rs.getString("faculty");
+ String institute = rs.getString("institute");
+ if (institute == null)
+ institute = "";
+ String street = rs.getString("street");
+ String zipCode = rs.getString("zip_code");
+ String city = rs.getString("city");
+ String country = rs.getString("country");
+ String webpage = rs.getString("webpage");
+ int contactID = rs.getInt("main_contact");
+ int headID = rs.getInt("head");
+ String contact = null;
+ String head = null;
+ if (contactID > 0) {
+ Person c = getPerson(contactID);
+ contact = c.getFirstName() + " " + c.getLastName();
+ }
+ if (headID > 0) {
+ Person h = getPerson(headID);
+ head = h.getFirstName() + " " + h.getLastName();
+ }
+ res = new Affiliation(id, groupName, acronym, organization, institute, faculty, contact,
+ head, street, zipCode, city, country, webpage);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res;
+ }
+
+ public Person getPerson(int id) {
+ Person res = null;
+ String sql = "SELECT * FROM persons WHERE persons.id = ?";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setInt(1, id);
+ ResultSet rs = statement.executeQuery();
+ while (rs.next()) {
+ String username = rs.getString("username");
+ String title = rs.getString("title");
+ String first = rs.getString("first_name");
+ String last = rs.getString("family_name");
+ String eMail = rs.getString("email");
+ String phone = rs.getString("phone");
+ res = new Person(username, title, first, last, eMail, phone, -1, null, null);// TODO add
+ // every
+ // affiliation?
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res;
+ }
+
+ private void endQuery(Connection c, PreparedStatement p) {
+ if (p != null)
+ try {
+ p.close();
+ } catch (Exception e) {
+ logger.error("PreparedStatement close problem");
+ }
+ if (c != null)
+ try {
+ logout(c);
+ } catch (Exception e) {
+ logger.error("Database Connection close problem");
+ }
+ }
+
+ public void setAffiliationVIP(int affi, int person, String role) {
+ logger.info("Trying to set/change affiliation-specific role " + role);
+ String sql = "UPDATE organizations SET " + role + "=? WHERE id = ?";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setInt(1, person);
+ statement.setInt(2, affi);
+ statement.execute();
+ logger.info("Successful for " + role);
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ endQuery(null, statement);
+ }
+ }
+
+ public List getPersonsByName(String one, String two) {
+ List res = new ArrayList();
+
+ String sql = "SELECT * from persons where (first_name LIKE ? AND family_name LIKE ?) OR "
+ + "(family_name LIKE ? AND first_name LIKE ?)";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setString(1, "%" + one + "%");
+ statement.setString(2, "%" + two + "%");
+ statement.setString(3, "%" + one + "%");
+ statement.setString(4, "%" + two + "%");
+ ResultSet rs = statement.executeQuery();
+ while (rs.next()) {
+ int id = rs.getInt("id");
+ List found = getPersonWithAffiliations(id);
+ if (found.isEmpty()) {
+ String username = rs.getString("username");
+ String title = rs.getString("title");
+ String first = rs.getString("first_name");
+ String last = rs.getString("family_name");
+ String eMail = rs.getString("email");
+ String phone = rs.getString("phone");
+ res.add(new Person(username, title, first, last, eMail, phone, -1, "N/A", "N/A"));
+ } else
+ res.add(found.get(0));// TODO set all of them!
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res;
+ }
+
+ public List getPersonsContaining(String personQuery) {
+ List res = new ArrayList();
+ personQuery = personQuery.trim();
+ if (personQuery.contains(" ")) {
+ String one = personQuery.split(" ")[0];
+ String two = personQuery.split(" ")[1];
+ res.addAll(getPersonsByName(one, two));
+ }
+
+ String sql = "SELECT * from persons where first_name LIKE ? OR family_name LIKE ?";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setString(1, "%" + personQuery + "%");
+ statement.setString(2, "%" + personQuery + "%");
+ ResultSet rs = statement.executeQuery();
+ while (rs.next()) {
+ int id = rs.getInt("id");
+ List found = getPersonWithAffiliations(id);
+ if (found.isEmpty()) {
+ String username = rs.getString("username");
+ String title = rs.getString("title");
+ String first = rs.getString("first_name");
+ String last = rs.getString("family_name");
+ String eMail = rs.getString("email");
+ String phone = rs.getString("phone");
+ res.add(new Person(username, title, first, last, eMail, phone, -1, "N/A", "N/A"));
+ } else
+ res.add(found.get(0));// TODO set all of them!
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res;
+ }
+
+ public List getAffiliationsContaining(String affiQuery) {
+ List res = new ArrayList();
+
+ String sql =
+ "SELECT * from organizations where group_name LIKE ? OR group_acronym LIKE ? OR umbrella_organization LIKE ? "
+ + "or institute LIKE ?";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ for (int i = 1; i < 5; i++)
+ statement.setString(i, "%" + affiQuery + "%");
+ ResultSet rs = statement.executeQuery();
+ while (rs.next()) {
+ int id = rs.getInt("id");
+ String groupName = rs.getString("group_name");
+ String acronym = rs.getString("group_acronym");
+ if (acronym == null)
+ acronym = "";
+ String organization = rs.getString("umbrella_organization");
+ String faculty = rs.getString("faculty");
+ String institute = rs.getString("institute");
+ if (institute == null)
+ institute = "";
+ String street = rs.getString("street");
+ String zipCode = rs.getString("zip_code");
+ String city = rs.getString("city");
+ String country = rs.getString("country");
+ String webpage = rs.getString("webpage");
+ int contactID = rs.getInt("main_contact");
+ int headID = rs.getInt("head");
+ String contact = null;
+ String head = null;
+ if (contactID > 0) {
+ Person c = getPerson(contactID);
+ contact = c.getFirstName() + " " + c.getLastName();
+ }
+ if (headID > 0) {
+ Person h = getPerson(headID);
+ head = h.getFirstName() + " " + h.getLastName();
+ }
+ res.add(new Affiliation(id, groupName, acronym, organization, institute, faculty, contact,
+ head, street, zipCode, city, country, webpage));
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res;
+ }
+
+ public Map getProjectMap() {
+ Map res = new HashMap();
+ // since there are at the moment 2 different roles, this query will return two rows per project
+ String sql =
+ "SELECT projects.*, projects.id, projects_persons.*, persons.first_name, persons.family_name FROM projects INNER JOIN projects_persons ON "
+ + "projects.id = projects_persons.project_id INNER JOIN persons ON projects_persons.person_id = persons.id";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ ResultSet rs = statement.executeQuery();
+ while (rs.next()) {
+ String projectID = rs.getString("openbis_project_identifier");
+ String[] openbisIDSplit = projectID.split("/");
+ String project = openbisIDSplit[2];
+ String role = rs.getString("project_role");
+ String name = rs.getString("first_name") + " " + rs.getString("family_name");
+ if (!res.containsKey(projectID)) {
+ // first result row
+ String space = openbisIDSplit[1];
+ int id = rs.getInt("project_id");
+ String shortName = rs.getString("short_title");
+ res.put(projectID, new ProjectInfo(space, project, "", shortName, id));
+ }
+ // setting person for different role rows
+ ProjectInfo info = res.get(projectID);
+ switch (role) {
+ case "PI":
+ info.setInvestigator(name);
+ break;
+ case "Contact":
+ info.setContact(name);
+ break;
+ case "Manager":
+ info.setManager(name);
+ break;
+ default:
+ logger.error("Unknown/unimplemented project role: " + role);
+ break;
+ }
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ // now we need to add all projects without person connections
+ sql =
+ "SELECT t1.* FROM projects t1 LEFT JOIN projects_persons t2 ON t1.id = t2.project_id WHERE t2.project_id IS NULL";
+ conn = login();
+ statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ ResultSet rs = statement.executeQuery();
+ while (rs.next()) {
+ String projID = rs.getString("openbis_project_identifier");
+ String[] openbisIDSplit = projID.split("/");
+ try {
+ String project = openbisIDSplit[2];
+ String space = openbisIDSplit[1];
+ int id = rs.getInt("id");
+ String shortName = rs.getString("short_title");
+ res.put(projID, new ProjectInfo(space, project, "", shortName, id));
+ } catch (Exception e) {
+ logger.error("Could not parse project from openbis identifier " + projID
+ + ". It seems this database entry is incorrect. Ignoring project.");
+ }
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res;
+ }
+
+ public List getCollaboratorsOfProject(String project) {
+ List res = new ArrayList();
+ // for experiments
+ String sql =
+ "SELECT experiments.*, experiments.id, experiments_persons.*, persons.first_name, persons.family_name FROM experiments INNER JOIN experiments_persons ON "
+ + "experiments.id = experiments_persons.experiment_id INNER JOIN persons ON experiments_persons.person_id = persons.id "
+ + "WHERE openbis_experiment_identifier LIKE ?";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setString(1, "%" + project + "%");
+ ResultSet rs = statement.executeQuery();
+ while (rs.next()) {
+ String openbisID = rs.getString("openbis_experiment_identifier");
+ String[] openbisIDSplit = openbisID.split("/");
+ int id = rs.getInt("experiments.id");
+ String exp = openbisIDSplit[3];
+ String role = rs.getString("experiment_role");
+ String name = rs.getString("first_name") + " " + rs.getString("family_name");
+ res.add(new CollaboratorWithResponsibility(id, name, openbisID, exp, role));
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ // now we need to add all projects without person connections
+ // sql =
+ // "SELECT t1.* FROM experiments t1 LEFT JOIN experiments_persons t2 ON t1.id = t2.experiment_id
+ // WHERE t2.experiment_id IS NULL";
+ // conn = login();
+ // statement = null;
+ // try {
+ // statement = conn.prepareStatement(sql);
+ // ResultSet rs = statement.executeQuery();
+ // while (rs.next()) {
+ // String[] openbisIDSplit = rs.getString("openbis_experiment_identifier").split("/");
+ // int id = rs.getInt("experiments.id");
+ // String exp = openbisIDSplit[3];
+ // String role = rs.getString("experiment_role");
+ // String name = rs.getString("first_name") + " " + rs.getString("family_name");
+ // res.add(new CollaboratorWithResponsibility(id, name, exp, role));
+ // }
+ // } catch (SQLException e) {
+ // e.printStackTrace();
+ // } finally {
+ // endQuery(conn, statement);
+ // }
+ return res;
+ }
+
+ public int addExperimentToDB(String openbisIdentifier) {
+ int exists = isExpInDB(openbisIdentifier);
+ if (exists < 0) {
+ logger.info("Trying to add experiment " + openbisIdentifier + " to the person DB");
+ String sql = "INSERT INTO experiments (openbis_experiment_identifier) VALUES(?)";
+ Connection conn = login();
+ try (PreparedStatement statement =
+ conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
+ statement.setString(1, openbisIdentifier);
+ statement.execute();
+ ResultSet rs = statement.getGeneratedKeys();
+ if (rs.next()) {
+ logout(conn);
+ logger.info("Successful.");
+ return rs.getInt(1);
+ }
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ }
+ logout(conn);
+ return -1;
+ }
+ return exists;
+ }
+
+ private int isExpInDB(String id) {
+ logger.info("Looking for experiment " + id + " in the DB");
+ String sql = "SELECT * from experiments WHERE openbis_experiment_identifier = ?";
+ int res = -1;
+ Connection conn = login();
+ try {
+ PreparedStatement statement = conn.prepareStatement(sql);
+ statement.setString(1, id);
+ ResultSet rs = statement.executeQuery();
+ if (rs.next()) {
+ logger.info("project found!");
+ res = rs.getInt("id");
+ }
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ }
+ logout(conn);
+ return res;
+ }
+
+ public void addPersonToExperiment(int expID, int personID, String role) {
+ if (expID == 0 || personID == 0)
+ return;
+
+ if (!hasPersonRoleInExperiment(personID, expID, role)) {
+ logger.info("Trying to add person with role " + role + " to an experiment.");
+ String sql =
+ "INSERT INTO experiments_persons (experiment_id, person_id, experiment_role) VALUES(?, ?, ?)";
+ Connection conn = login();
+ try (PreparedStatement statement =
+ conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
+ statement.setInt(1, expID);
+ statement.setInt(2, personID);
+ statement.setString(3, role);
+ statement.execute();
+ logger.info("Successful.");
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ }
+ logout(conn);
+ }
+ }
+
+ private boolean hasPersonRoleInExperiment(int personID, int expID, String role) {
+ logger.info("Checking if person already has this role in the experiment.");
+ String sql =
+ "SELECT * from experiments_persons WHERE person_id = ? AND experiment_id = ? and experiment_role = ?";
+ boolean res = false;
+ Connection conn = login();
+ try {
+ PreparedStatement statement = conn.prepareStatement(sql);
+ statement.setInt(1, personID);
+ statement.setInt(2, expID);
+ statement.setString(3, role);
+ ResultSet rs = statement.executeQuery();
+ if (rs.next()) {
+ res = true;
+ logger.info("person already has this role!");
+ }
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ }
+ logout(conn);
+ return res;
+ }
+
+ public int getProjectIDFromCode(String code) {
+ int res = -1;
+ String sql = "SELECT id from projects WHERE openbis_project_identifier LIKE ?";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setString(1, "%" + code);
+ ResultSet rs = statement.executeQuery();
+ while (rs.next()) {
+ res = rs.getInt("id");
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ return res;
+ }
+
+ public void removePersonFromProject(int id, String role) {
+ logger.info("Trying to remove person with role " + role + " from project with id " + id);
+ String sql = "DELETE FROM projects_persons WHERE project_id = ? AND project_role = ?";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setInt(1, id);
+ statement.setString(2, role);
+ statement.executeQuery();
+ logger.info("Successful.");
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ }
+
+ public void removePersonFromExperiment(int experimentID) {
+ logger.info("Trying to remove person from experiment with id " + experimentID);
+ String sql = "DELETE FROM experiments_persons WHERE experiment_id = ?";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql);
+ statement.setInt(1, experimentID);
+ statement.executeQuery();
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ }
+
+ public void addOrUpdatePersonToExperiment(int experimentID, int personID, String role) {
+ if (!hasPersonRoleInExperiment(personID, experimentID, role)) {
+ logger.info("Trying to add person with role " + role + " to an experiment.");
+ if (!roleForExperimentTaken(experimentID, role)) {
+ logger.info("Role " + role + " is not yet taken.");
+ String sql =
+ "INSERT INTO experiments_persons (experiment_id, person_id, experiment_role) VALUES(?, ?, ?)";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
+ statement.setInt(1, experimentID);
+ statement.setInt(2, personID);
+ statement.setString(3, role);
+ statement.execute();
+ logger.info("Successful.");
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ } else {
+ logger.info("Role " + role + " is taken. Updating to new person.");
+ String sql =
+ "UPDATE experiments_persons SET person_id = ? WHERE experiment_id = ? AND experiment_role = ?;";
+ Connection conn = login();
+ PreparedStatement statement = null;
+ try {
+ statement = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
+ statement.setInt(1, personID);
+ statement.setInt(2, experimentID);
+ statement.setString(3, role);
+ statement.execute();
+ logger.info("Successful.");
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ endQuery(conn, statement);
+ }
+ }
+ }
+ }
+
+ public boolean personExists(Person p) {
+ String username = p.getUsername();
+ String email = p.getEmail();
+ logger.info("Looking for user " + username + " in the DB");
+ String sql = "SELECT * from persons WHERE UPPER(username) = UPPER(?)";
+ boolean res = false;
+ Connection conn = login();
+ try {
+ PreparedStatement statement = conn.prepareStatement(sql);
+ statement.setString(1, username);
+ ResultSet rs = statement.executeQuery();
+ if (rs.next()) {
+ logger.info("user found!");
+ res = true;
+ }
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ }
+ if (res)
+ return res;
+ logger.info("Looking for user with email " + email + " in the DB");
+ sql = "SELECT * from persons WHERE UPPER(email) = UPPER(?)";
+ try {
+ PreparedStatement statement = conn.prepareStatement(sql);
+ statement.setString(1, email);
+ ResultSet rs = statement.executeQuery();
+ if (rs.next()) {
+ logger.info("email found!");
+ res = true;
+ }
+ } catch (SQLException e) {
+ logger.error("SQL operation unsuccessful: " + e.getMessage());
+ e.printStackTrace();
+ }
+ logout(conn);
+ return res;
+ }
+}
diff --git a/user-db-portlet/src/main/java/life/qbic/userdb/DBVocabularies.java b/user-db-portlet/src/main/java/life/qbic/userdb/DBVocabularies.java
new file mode 100644
index 0000000..2f5f408
--- /dev/null
+++ b/user-db-portlet/src/main/java/life/qbic/userdb/DBVocabularies.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * QBiC User DB Tools enables users to add people and affiliations to our mysql user database.
+ * Copyright (C) 2016 Andreas Friedrich
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *******************************************************************************/
+package life.qbic.userdb;
+
+import java.util.List;
+import java.util.Map;
+
+
+public class DBVocabularies {
+
+ private Map taxMap;
+ private Map tissueMap;
+ private Map deviceMap;
+ private Map cellLinesMap;
+ private List measureTypes;
+ private List spaces;
+ private Map investigators;
+ private List experimentTypes;
+ private List enzymes;
+ private List msProtocols;
+ private List lcmsMethods;
+ private List chromTypes;
+
+ public DBVocabularies(Map taxMap, Map tissueMap,
+ Map cellLinesMap, List measureTypes, List spaces,
+ Map piMap, List experimentTypes, List enzymes,
+ Map deviceMap, List msProtocols, List lcmsMethods,
+ List chromTypes) {
+ this.taxMap = taxMap;
+ this.tissueMap = tissueMap;
+ this.cellLinesMap = cellLinesMap;
+ this.deviceMap = deviceMap;
+ this.measureTypes = measureTypes;
+ this.spaces = spaces;
+ this.investigators = piMap;
+ this.experimentTypes = experimentTypes;
+ this.enzymes = enzymes;
+ this.msProtocols = msProtocols;
+ this.lcmsMethods = lcmsMethods;
+ this.chromTypes = chromTypes;
+ }
+
+ public Map getCellLinesMap() {
+ return cellLinesMap;
+ }
+
+ public Map getTaxMap() {
+ return taxMap;
+ }
+
+ public Map getTissueMap() {
+ return tissueMap;
+ }
+
+ public Map getDeviceMap() {
+ return deviceMap;
+ }
+
+ public List getMeasureTypes() {
+ return measureTypes;
+ }
+
+ public List getSpaces() {
+ return spaces;
+ }
+
+ public Map getInvestigators() {
+ return investigators;
+ }
+
+ public List getExperimentTypes() {
+ return experimentTypes;
+ }
+
+ public List getEnzymes() {
+ return enzymes;
+ }
+
+ public List getMsProtocols() {
+ return msProtocols;
+ }
+
+ public List getLcmsMethods() {
+ return lcmsMethods;
+ }
+
+ public List getChromTypes() {
+ return chromTypes;
+ }
+
+}
diff --git a/user-db-portlet/src/main/java/life/qbic/userdb/helpers/PersonBatchReader.java b/user-db-portlet/src/main/java/life/qbic/userdb/helpers/PersonBatchReader.java
new file mode 100644
index 0000000..8ff1e82
--- /dev/null
+++ b/user-db-portlet/src/main/java/life/qbic/userdb/helpers/PersonBatchReader.java
@@ -0,0 +1,168 @@
+package life.qbic.userdb.helpers;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.bind.JAXBException;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import life.qbic.datamodel.persons.Person;
+
+public class PersonBatchReader {
+
+ private static final Logger logger = LogManager.getLogger(PersonBatchReader.class);
+ private List mandatory;
+ private List optional;
+
+ private String error;
+ private List tsvByRows;
+ private List people;
+
+ public PersonBatchReader() {
+ Set mandatory =
+ new HashSet(Arrays.asList("first name", "last name", "title", "email"));
+ //
+ this.mandatory = new ArrayList(mandatory);
+ Set optional = new HashSet(Arrays.asList("phone", "username"));
+ this.optional = new ArrayList(optional);
+ }
+
+ public static void main(String[] args) throws JAXBException {
+ try {
+ PersonBatchReader p = new PersonBatchReader();
+ if (p.readPeopleFile(new File("/Users/frieda/Desktop/person_import.tsv")))
+ System.out.println(p.getPeople());
+ else
+ System.out.println(p.getError());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public List getPeople() {
+ return people;
+ }
+
+ public static final String UTF8_BOM = "\uFEFF";
+
+ private static String removeUTF8BOM(String s) {
+ if (s.startsWith(UTF8_BOM)) {
+ s = s.substring(1);
+ }
+ return s;
+ }
+
+ /**
+ * Reads in a TSV file containing samples that should be registered. Returns a List of
+ * TSVSampleBeans containing all the necessary information to register each sample with its meta
+ * information to openBIS, given that the types and parents exist.
+ *
+ * @param file
+ * @return ArrayList of TSVSampleBeans
+ * @throws IOException
+ * @throws JAXBException
+ */
+ public boolean readPeopleFile(File file) throws IOException {
+ people = new ArrayList();
+ tsvByRows = new ArrayList();
+ BufferedReader reader = new BufferedReader(new FileReader(file));
+ ArrayList data = new ArrayList();
+ String next;
+ int i = 0;
+ // isPilot = false;
+ while ((next = reader.readLine()) != null) {
+ i++;
+ next = removeUTF8BOM(next);
+ tsvByRows.add(next);
+ String[] nextLine = next.split("\t", -1);// this is needed for trailing tabs
+ if (data.isEmpty() || nextLine.length == data.get(0).length) {
+ data.add(nextLine);
+ } else {
+ error = "Wrong number of columns in row " + i;
+ reader.close();
+ return false;
+ }
+ }
+ reader.close();
+
+ if(data.isEmpty()) {
+ error = "File is empty.";
+ return false;
+ }
+ String[] header = data.get(0);
+ data.remove(0);
+
+ Map headerMapping = new HashMap();
+
+ ArrayList found = new ArrayList(Arrays.asList(header));
+ for (int j = 0; j < found.size(); j++)
+ found.set(j, found.get(j).toLowerCase());
+
+ for (String col : mandatory) {
+ if (!found.contains(col)) {
+ error = "Mandatory column " + col + " not found.";
+ return false;
+ }
+ }
+ for (i = 0; i < header.length; i++) {
+ String name = header[i].toLowerCase();
+ int position = mandatory.indexOf(name);
+ if (position > -1) {
+ headerMapping.put(name, i);
+ } else {
+ position = optional.indexOf(name);
+ if (position > -1) {
+ headerMapping.put(name, i);
+ }
+ }
+
+ }
+ // create person objects
+ int rowID = 0;
+ for (String[] row : data) {
+ rowID++;
+ for (String col : mandatory) {
+ if (row[headerMapping.get(col)].isEmpty()) {
+ error = col + " is a mandatory field, but it is not set for row " + rowID + "!";
+ return false;
+ }
+ }
+
+ String first = row[headerMapping.get("first name")];
+ String last = row[headerMapping.get("last name")];
+ String title = row[headerMapping.get("title")];
+ String mail = row[headerMapping.get("email")];
+ Person p = new Person(title, first, last, mail);
+ if (headerMapping.get("phone") != null)
+ p.setPhone(row[headerMapping.get("phone")]);
+ if (headerMapping.get("username") != null)
+ p.setUsername(row[headerMapping.get("username")]);
+ people.add(p);
+ }
+ return true;
+ }
+
+ public String getError() {
+ if (error != null)
+ logger.error(error);
+ else
+ logger.info("Parsing of experimental design successful.");
+ return error;
+ }
+
+ public List getTSVByRows() {
+ return tsvByRows;
+ }
+
+}
diff --git a/user-db-portlet/src/main/java/life/qbic/userdb/helpers/RegExHelper.java b/user-db-portlet/src/main/java/life/qbic/userdb/helpers/RegExHelper.java
new file mode 100644
index 0000000..e109002
--- /dev/null
+++ b/user-db-portlet/src/main/java/life/qbic/userdb/helpers/RegExHelper.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * QBiC User DB Tools enables users to add people and affiliations to our mysql user database.
+ * Copyright (C) 2016 Andreas Friedrich
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *******************************************************************************/
+package life.qbic.userdb.helpers;
+
+public class RegExHelper {
+ public static final String VALID_EMAIL_ADDRESS_REGEX =
+ "(?:(?:\\r\\n)?[ \\t])*(?:(?:(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*|(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)*\\<(?:(?:\\r\\n)?[ \\t])*(?:@(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*(?:,@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*)*:(?:(?:\\r\\n)?[ \\t])*)?(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*\\>(?:(?:\\r\\n)?[ \\t])*)|(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)*:(?:(?:\\r\\n)?[ \\t])*(?:(?:(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*|(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)*\\<(?:(?:\\r\\n)?[ \\t])*(?:@(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*(?:,@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*)*:(?:(?:\\r\\n)?[ \\t])*)?(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*\\>(?:(?:\\r\\n)?[ \\t])*)(?:,\\s*(?:(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*|(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)*\\<(?:(?:\\r\\n)?[ \\t])*(?:@(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*(?:,@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*)*:(?:(?:\\r\\n)?[ \\t])*)?(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*\\>(?:(?:\\r\\n)?[ \\t])*))*)?;\\s*)";
+ public static final String VALID_URL_REGEX =
+ "^(http://|https://)?(www.)?([a-zA-Z0-9]+).[a-zA-Z0-9]*-?[a-zA-Z0-9]*.[a-z]{3}.?([a-z]+)?/?$";
+ public static final String VALID_USERNAME_REGEX = "[a-z]+[0-9a-z]*";
+ public static final String VALID_NAME_REGEX = "[A-ZÖÄÜa-zöäüß]+[\\sA-ZÄÖÜa-zöäüß-]*";
+ //public static final String VALID_PHONE_NUMBER = "[\\+]?[[0-9]0?]+";
+}
diff --git a/user-db-portlet/src/main/java/life/qbic/userdb/helpers/Uploader.java b/user-db-portlet/src/main/java/life/qbic/userdb/helpers/Uploader.java
new file mode 100644
index 0000000..9bb7e77
--- /dev/null
+++ b/user-db-portlet/src/main/java/life/qbic/userdb/helpers/Uploader.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * ''' * QBiC User DB Tools enables users to add people and affiliations to our mysql user database.
+ * Copyright (C) 2016 Andreas Friedrich
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ *******************************************************************************/
+package life.qbic.userdb.helpers;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+
+import org.apache.commons.io.FilenameUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import com.vaadin.ui.Upload;
+
+import life.qbic.portal.portlet.UserDBPortletUI;
+
+/**
+ * Uploader for tsv files
+ *
+ * @author Andreas Friedrich
+ *
+ */
+@SuppressWarnings("serial")
+public class Uploader implements Upload.SucceededListener, Upload.FailedListener, Upload.Receiver {
+
+ private File file; // File to write to.
+ private String error;
+
+ private final static Logger logger = LogManager.getLogger(Uploader.class);
+ private String fileName;
+
+ public Uploader() {}
+
+ /**
+ * Callback method to begin receiving the upload.
+ */
+ public OutputStream receiveUpload(String filename, String MIMEType) {
+ FileOutputStream fos = null; // Output stream to write to
+ error = null;
+ fileName = filename;
+ file = new File(UserDBPortletUI.tmpFolder + "up_" + filename);
+ // TODO probably not needed; some browsers set MIME information to application/octet-stream,
+ // which leads to bug
+ // if (!MIMEType.equals("text/plain") && !MIMEType.equals("text/tab-separated-values")) {
+ // error = "Wrong File type. Please only upload tsv or txt files.";
+ // }
+ try {
+ // Open the file for writing.
+ fos = new FileOutputStream(file);
+ } catch (FileNotFoundException e) {
+ // Error while opening the file. Not reported here.
+ e.printStackTrace();
+ return null;
+ }
+ return fos; // Return the output stream to write to
+ }
+
+ public String getError() {
+ return error;
+ }
+
+ public String getBaseFileName() {
+ return fileName;
+ }
+
+ public String getFileNameWithoutExtension() {
+ return FilenameUtils.removeExtension(fileName);
+ }
+
+ public File getFile() {
+ return file;
+ }
+
+ /**
+ * This is called if the upload is finished.
+ */
+ public void uploadSucceeded(Upload.SucceededEvent event) {
+ // Display the uploaded file in the image panel.
+ logger.info(
+ "Uploading " + event.getFilename() + " of type '" + event.getMIMEType() + "' successful.");
+ }
+
+ /**
+ * This is called if the upload fails.
+ */
+ public void uploadFailed(Upload.FailedEvent event) {
+ // Log the failure on screen.
+ logger.error(
+ "Uploading " + event.getFilename() + " of type '" + event.getMIMEType() + "' failed.");
+ }
+}
diff --git a/user-db-portlet/src/main/java/life/qbic/userdb/model/Minutes.java b/user-db-portlet/src/main/java/life/qbic/userdb/model/Minutes.java
new file mode 100644
index 0000000..727bf93
--- /dev/null
+++ b/user-db-portlet/src/main/java/life/qbic/userdb/model/Minutes.java
@@ -0,0 +1,54 @@
+package life.qbic.userdb.model;
+
+public class Minutes {
+
+ private int id;
+ private String purpose;
+ private String participants;
+ private String agenda;
+ private String discussion;
+ private String results;
+ private String nextSteps;
+
+ public Minutes(int id, String purpose, String participants, String agenda, String discussion,
+ String results, String nextSteps) {
+ super();
+ this.id = id;
+ this.purpose = purpose;
+ this.participants = participants;
+ this.agenda = agenda;
+ this.discussion = discussion;
+ this.results = results;
+ this.nextSteps = nextSteps;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public String getPurpose() {
+ return purpose;
+ }
+
+ public String getParticipants() {
+ return participants;
+ }
+
+ public String getAgenda() {
+ return agenda;
+ }
+
+ public String getDiscussion() {
+ return discussion;
+ }
+
+ public String getResults() {
+ return results;
+ }
+
+ public String getNextSteps() {
+ return nextSteps;
+ }
+
+
+}
diff --git a/user-db-portlet/src/main/java/life/qbic/userdb/views/AffiliationInput.java b/user-db-portlet/src/main/java/life/qbic/userdb/views/AffiliationInput.java
new file mode 100644
index 0000000..5a2806c
--- /dev/null
+++ b/user-db-portlet/src/main/java/life/qbic/userdb/views/AffiliationInput.java
@@ -0,0 +1,225 @@
+/*******************************************************************************
+ * QBiC User DB Tools enables users to add people and affiliations to our mysql user database.
+ * Copyright (C) 2016 Andreas Friedrich
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ *******************************************************************************/
+package life.qbic.userdb.views;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import com.vaadin.shared.ui.combobox.FilteringMode;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.ComboBox;
+import com.vaadin.ui.FormLayout;
+import com.vaadin.ui.TextField;
+import com.vaadin.ui.themes.ValoTheme;
+
+import life.qbic.datamodel.persons.Affiliation;
+import life.qbic.portal.Styles;
+
+public class AffiliationInput extends FormLayout {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 2499215556258217023L;
+ private TextField groupName;
+ private TextField acronym;
+ private TextField organization;
+ private ComboBox institute;
+ private ComboBox faculty;
+ private ComboBox contactPerson;
+ private ComboBox head;
+ private TextField street;
+ private TextField zipCode;
+ private TextField city;
+ private TextField country;
+ private TextField webpage;
+
+ private Map personMap;
+
+ private Button commit;
+
+ Logger logger = LogManager.getLogger(AffiliationInput.class);
+
+ public AffiliationInput(Set institutes, List faculties,
+ Map personMap) {
+ setMargin(true);
+
+ this.personMap = personMap;
+
+ groupName = new TextField("Group Name");
+ groupName.setWidth("300px");
+ addComponent(groupName);
+
+ acronym = new TextField("Acronym");
+ acronym.setWidth("300px");
+ addComponent(Styles.questionize(acronym,
+ "Short acronym of the lowest level of this affiliation, "
+ + "e.g. of the group if specified or of the institute if group field is left empty.",
+ "Acronym"));
+
+ organization = new TextField("Organization");
+ organization.setWidth("300px");
+ organization.setRequired(true);
+ organization.setInputPrompt("...or university name");
+ organization.setDescription("Organization or University Name");
+ addComponent(organization);
+
+ institute = new ComboBox("Institute", institutes);
+ institute.setWidth("300px");
+ institute.setNewItemsAllowed(true);
+ institute.setStyleName(ValoTheme.COMBOBOX_SMALL);
+ institute.setFilteringMode(FilteringMode.CONTAINS);
+ // institute.setRequired(true);
+ addComponent(Styles.questionize(institute, "Select existing institutes or input a new one.",
+ "Institute"));
+
+ faculty = new ComboBox("Faculty", faculties);
+ faculty.setRequired(true);
+ faculty.setStyleName(ValoTheme.COMBOBOX_SMALL);
+ faculty.setWidth("300px");
+ addComponent(Styles.questionize(faculty,
+ "Faculty of the institute/affiliation. University affiliations like QBiC "
+ + "that are neither part of Medical nor Science Faculty belong to Central Units. "
+ + "For non-university affiliations select Other.",
+ "Faculty"));
+
+ contactPerson = new ComboBox("Contact Person", personMap.keySet());
+ contactPerson.setWidth("300px");
+ contactPerson.setFilteringMode(FilteringMode.CONTAINS);
+ contactPerson.setStyleName(ValoTheme.COMBOBOX_SMALL);
+ // contactPerson.setRequired(true);
+ addComponent(Styles.questionize(contactPerson, "Main contact person of this affiliation.",
+ "Contact Person"));
+
+ head = new ComboBox("Head", personMap.keySet());
+ head.setWidth("300px");
+ head.setFilteringMode(FilteringMode.CONTAINS);
+ // head.setRequired(true);
+ head.setStyleName(ValoTheme.COMBOBOX_SMALL);
+ addComponent(Styles.questionize(head, "Head of this affiliation.", "Head"));
+
+ street = new TextField("Street");
+ street.setWidth("300px");
+ street.setRequired(true);
+ addComponent(street);
+
+ zipCode = new TextField("Zip Code");
+ zipCode.setWidth("300px");
+ zipCode.setRequired(true);
+ addComponent(zipCode);
+
+ city = new TextField("City");
+ city.setWidth("300px");
+ city.setRequired(true);
+ addComponent(city);
+
+ country = new TextField("Country");
+ country.setWidth("300px");
+ country.setRequired(true);
+ addComponent(country);
+
+ webpage = new TextField("Webpage");
+ webpage.setWidth("300px");
+ // TODO webpage formats are difficult
+ // webpage.addValidator(
+ // new RegexpValidator(Helpers.VALID_URL_REGEX, "This is not a valid web page format."));
+ addComponent(webpage);
+
+ commit = new Button("Register Affiliation");
+ addComponent(commit);
+ }
+
+ public boolean isValid() {
+ return groupName.isValid() && acronym.isValid() && organization.isValid() && institute.isValid()
+ && faculty.isValid() && contactPerson.isValid() && head.isValid() && street.isValid()
+ && zipCode.isValid() && country.isValid() && city.isValid() && webpage.isValid();
+ }
+
+ public Button getCommitButton() {
+ return commit;
+ }
+
+ private int mapPersonToID(String person) {
+ if (person == null) {
+ logger.info("No optional person provided for new affiliation. Field will be empty.");
+ return -1;
+ } else
+ return personMap.get(person);
+ }
+
+ public TextField getOrganizationField() {
+ return organization;
+ }
+
+ public Affiliation getAffiliation() {
+ String inst = null;
+ if (institute.getValue() != null)
+ inst = institute.getValue().toString();
+ String contact = null;
+ if (contactPerson.getValue() != null)
+ contact = contactPerson.getValue().toString();
+ String headPerson = null;
+ if (head.getValue() != null)
+ headPerson = head.getValue().toString();
+
+ int contactID = mapPersonToID(contact);
+ int headID = mapPersonToID(headPerson);
+
+ String fac = faculty.getValue().toString();
+ return new Affiliation(groupName.getValue(), acronym.getValue(), organization.getValue(), inst,
+ fac, contactID, headID, street.getValue(), zipCode.getValue(), city.getValue(),
+ country.getValue(), webpage.getValue());
+ }
+
+ public void autoComplete(Affiliation affiliation) {
+ organization.setValue(affiliation.getOrganization());
+ institute.setValue(affiliation.getInstitute());
+ faculty.setValue(affiliation.getFaculty());
+ street.setValue(affiliation.getStreet());
+ city.setValue(affiliation.getCity());
+ zipCode.setValue(affiliation.getZipCode());
+ country.setValue(affiliation.getCountry());
+ }
+
+ public ComboBox getInstituteField() {
+ return institute;
+ }
+
+ public void hideRegisterButton() {
+ commit.setEnabled(false);
+ commit.setVisible(false);
+ }
+
+ public void reset() {
+ groupName.setValue("");
+ acronym.setValue("");
+ organization.setValue("");
+ institute.setValue(institute.getNullSelectionItemId());
+ faculty.setValue(faculty.getNullSelectionItemId());
+ contactPerson.setValue(contactPerson.getNullSelectionItemId());
+ head.setValue(head.getNullSelectionItemId());
+ street.setValue("");
+ zipCode.setValue("");
+ city.setValue("");
+ country.setValue("");
+ webpage.setValue("");
+ }
+
+}
diff --git a/user-db-portlet/src/main/java/life/qbic/userdb/views/AffiliationVIPTab.java b/user-db-portlet/src/main/java/life/qbic/userdb/views/AffiliationVIPTab.java
new file mode 100644
index 0000000..a451e05
--- /dev/null
+++ b/user-db-portlet/src/main/java/life/qbic/userdb/views/AffiliationVIPTab.java
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * QBiC User DB Tools enables users to add people and affiliations to our mysql user database.
+ * Copyright (C) 2016 Andreas Friedrich
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
+ *******************************************************************************/
+package life.qbic.userdb.views;
+
+import java.util.Map;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+
+import com.vaadin.data.Property.ValueChangeEvent;
+import com.vaadin.data.Property.ValueChangeListener;
+import com.vaadin.server.FontAwesome;
+import com.vaadin.shared.ui.combobox.FilteringMode;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.ComboBox;
+import com.vaadin.ui.FormLayout;
+import com.vaadin.ui.themes.ValoTheme;
+
+import life.qbic.portal.Styles;
+
+public class AffiliationVIPTab extends FormLayout {
+
+ private ComboBox affiTabOrgs;
+ private ComboBox head;
+ private ComboBox contact;
+ private Button commitAffiTabButton;
+
+ private Map affiliationMap;
+ private Map personMap;
+ private Map> personAffiliationsInTable;
+
+
+ public AffiliationVIPTab(Map persons, Map affiliations,
+ Map> affiPeople) {
+
+ this.affiliationMap = affiliations;
+ this.personMap = persons;
+ this.personAffiliationsInTable = affiPeople;
+
+ affiTabOrgs = new ComboBox("Affiliation", affiliations.keySet());
+ affiTabOrgs.setStyleName(ValoTheme.COMBOBOX_SMALL);
+ affiTabOrgs.setFilteringMode(FilteringMode.CONTAINS);
+ affiTabOrgs.addValueChangeListener(new ValueChangeListener() {
+
+ @Override
+ public void valueChange(ValueChangeEvent event) {
+ Object val = affiTabOrgs.getValue();
+ contact.setVisible(val != null);
+ head.setVisible(val != null);
+ if (val != null) {
+ String affiName = val.toString();
+ int id = affiliations.get(affiName);
+ Pair names = personAffiliationsInTable.get(id);
+ contact.setValue(names.getLeft());
+ head.setValue(names.getRight());
+ }
+ }
+ });
+
+ head = new ComboBox("Head", persons.keySet());
+ head.setStyleName(ValoTheme.COMBOBOX_SMALL);
+ head.setFilteringMode(FilteringMode.CONTAINS);
+ head.setVisible(false);
+ contact = new ComboBox("Contact Person", persons.keySet());
+ contact.setStyleName(ValoTheme.COMBOBOX_SMALL);
+ contact.setFilteringMode(FilteringMode.CONTAINS);
+ contact.setVisible(false);
+ ValueChangeListener personListener = new ValueChangeListener() {
+
+ @Override
+ public void valueChange(ValueChangeEvent event) {
+ boolean hasData = head.getValue() != null || contact.getValue() != null;
+ commitAffiTabButton.setEnabled(hasData);
+ }
+ };
+ head.addValueChangeListener(personListener);
+ contact.addValueChangeListener(personListener);
+
+ commitAffiTabButton = new Button("Save Contact");
+ commitAffiTabButton.setEnabled(false);
+
+ addComponent(affiTabOrgs);
+ addComponent(head);
+ addComponent(contact);
+ commitAffiTabButton.setIcon(FontAwesome.SAVE);
+ addComponent(Styles.questionize(commitAffiTabButton,
+ "Add or change records to the selected people. "
+ + "Existing people can only be replaced by a new selection, empty selections are ignored.",
+ "Save Changes"));
+ }
+
+
+ public int getNewHeadID() {
+ Object val = head.getValue();
+ if (val != null) {
+ String headName = val.toString();
+ return personMap.get(headName);
+ } else
+ return -1;
+ }
+
+ public int getNewContactID() {
+ Object val = contact.getValue();
+ if (val != null) {
+ String contactName = val.toString();
+ return personMap.get(contactName);
+ } else
+ return -1;
+ }
+
+ public int getSelectedAffiTabID() {
+ Object val = affiTabOrgs.getValue();
+ if (val != null) {
+ String affiName = val.toString();
+ return affiliationMap.get(affiName);
+ } else
+ return -1;
+ }
+
+ public void updateVIPs() {
+ int affi = getSelectedAffiTabID();
+ Object ctct = contact.getValue();
+ Object hd = head.getValue();
+ if (ctct == null)
+ ctct = personAffiliationsInTable.get(affi).getLeft();
+ if (hd == null)
+ hd = personAffiliationsInTable.get(affi).getRight();
+ personAffiliationsInTable.put(affi,
+ new ImmutablePair((String) ctct, (String) hd));
+ }
+
+ public Button getSetHeadAndContactButton() {
+ return commitAffiTabButton;
+ }
+}
diff --git a/user-db-portlet/src/main/java/life/qbic/userdb/views/EntryInput.java b/user-db-portlet/src/main/java/life/qbic/userdb/views/EntryInput.java
new file mode 100644
index 0000000..dbf3d41
--- /dev/null
+++ b/user-db-portlet/src/main/java/life/qbic/userdb/views/EntryInput.java
@@ -0,0 +1,89 @@
+package life.qbic.userdb.views;
+
+import java.util.List;
+import java.util.Map;
+
+import com.vaadin.data.validator.RegexpValidator;
+import com.vaadin.shared.ui.combobox.FilteringMode;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.ComboBox;
+import com.vaadin.ui.FormLayout;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.TextField;
+import com.vaadin.ui.themes.ValoTheme;
+
+import life.qbic.portal.Styles;
+import life.qbic.userdb.helpers.RegExHelper;
+
+public class EntryInput extends HorizontalLayout {
+
+ private FormLayout personInput;
+ private FormLayout groupInput;
+ private Button commit;
+ private TextField userName;
+ private ComboBox title;
+ private TextField first;
+ private TextField last;
+ private TextField eMail;
+ private TextField phone;
+ private ComboBox affiliation;
+ private ComboBox role;
+
+ public EntryInput(List titles, Map affiliations, List roles) {
+ setMargin(true);
+
+ userName = new TextField("Username");
+ // userName.setRequired(true);
+ userName.addValidator(
+ new RegexpValidator(RegExHelper.VALID_USERNAME_REGEX, "Please input a valid username."));
+ addComponent(Styles.questionize(userName,
+ "University Tübingen user name or user name provided by QBiC. If left empty a dummy user name is chosen "
+ + "which cannot be used to log in until a real name is added. Person information can still be added to "
+ + "projects or experiments in that case.",
+ "User Name"));
+
+ title = new ComboBox("Title", titles);
+ title.setRequired(true);
+ title.setStyleName(ValoTheme.COMBOBOX_SMALL);
+ title.setNullSelectionAllowed(false);
+ addComponent(title);
+
+ first = new TextField("First Name");
+ first.setRequired(true);
+ first.addValidator(new RegexpValidator(RegExHelper.VALID_NAME_REGEX, "Please input a valid name."));
+ addComponent(first);
+
+ last = new TextField("Last Name");
+ last.setRequired(true);
+ last.addValidator(new RegexpValidator(RegExHelper.VALID_NAME_REGEX, "Please input a valid name."));
+ addComponent(last);
+
+ eMail = new TextField("E-Mail");
+ eMail.setRequired(true);
+ eMail.addValidator(new RegexpValidator(RegExHelper.VALID_EMAIL_ADDRESS_REGEX,
+ "Please input a valid e-mail address."));
+ addComponent(eMail);
+
+ phone = new TextField("Phone");
+ addComponent(phone);
+
+ affiliation = new ComboBox("Affiliation", affiliations.keySet());
+ affiliation.setNullSelectionAllowed(false);
+ affiliation.setRequired(true);
+ affiliation.setFilteringMode(FilteringMode.CONTAINS);
+ affiliation.setStyleName(ValoTheme.COMBOBOX_SMALL);
+ addComponent(Styles.questionize(affiliation,
+ "Work group or organization this person is part of. If it does not exist in the system "
+ + "a \"New Affiliation\" has to be created first. Additional Affiliations and roles can be set in the next Tab.",
+ "Affiliation"));
+
+ role = new ComboBox("Role", roles);
+ role.setRequired(true);
+ role.setStyleName(ValoTheme.COMBOBOX_SMALL);
+ role.setNullSelectionAllowed(false);
+ addComponent(role);
+
+ commit = new Button("Register User");
+ addComponent(commit);
+ }
+}
diff --git a/user-db-portlet/src/main/java/life/qbic/userdb/views/MultiAffiliationTab.java b/user-db-portlet/src/main/java/life/qbic/userdb/views/MultiAffiliationTab.java
new file mode 100644
index 0000000..ab910d4
--- /dev/null
+++ b/user-db-portlet/src/main/java/life/qbic/userdb/views/MultiAffiliationTab.java
@@ -0,0 +1,212 @@
+/*******************************************************************************
+ * QBiC User DB Tools enables users to add people and affiliations to our mysql user database.
+ * Copyright (C) 2016 Andreas Friedrich
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *******************************************************************************/
+package life.qbic.userdb.views;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.vaadin.shared.ui.combobox.FilteringMode;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.ComboBox;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.themes.ValoTheme;
+
+import life.qbic.datamodel.persons.Person;
+import life.qbic.datamodel.persons.PersonAffiliationConnectionInfo;
+import life.qbic.datamodel.persons.RoleAt;
+
+public class MultiAffiliationTab extends VerticalLayout {
+
+ // private TabSheet tabs;
+ // private FormLayout personTab;
+
+ private ComboBox organization;
+ private ComboBox person;
+ private Button addToTable;
+
+ private Table table;
+
+ // private Button setContactPerson;
+ private Button commit;
+
+ // private FormLayout affiTab;
+
+
+ private Map affiliationMap;
+ private Map personMap;
+ private List availableRoles;
+ private Map personAffiliationsInTable;
+ private String currentPerson;
+
+ public MultiAffiliationTab(Map persons, Map affiliations,
+ List roles) {
+ // tabs = new TabSheet();
+ // personTab = new FormLayout();
+ setMargin(true);
+ setSpacing(true);
+ this.affiliationMap = affiliations;
+ this.personMap = persons;
+ this.availableRoles = roles;
+
+ person = new ComboBox("Person", persons.keySet());
+ person.setStyleName(ValoTheme.COMBOBOX_SMALL);
+ person.setFilteringMode(FilteringMode.CONTAINS);
+ person.setNullSelectionAllowed(false);
+ addComponent(person);
+ organization = new ComboBox("Organization", affiliations.keySet());
+ organization.setNullSelectionAllowed(false);
+ organization.setStyleName(ValoTheme.COMBOBOX_SMALL);
+ organization.setFilteringMode(FilteringMode.CONTAINS);
+ addComponent(organization);
+
+ addToTable = new Button("Add to Preview");
+ addComponent(addToTable);
+ addToTable.setEnabled(false);
+
+ table = new Table();
+ table.setWidthUndefined();
+ // table.addContainerProperty("Title", String.class, null);
+ // table.addContainerProperty("First Name", String.class, null);
+ // table.addContainerProperty("Family Name", String.class, null);
+ table.addContainerProperty("Affiliation", String.class, null);
+ table.setColumnWidth("Affiliation", 250);
+ table.addContainerProperty("Role", ComboBox.class, null);
+ // table.addContainerProperty("Main Contact", CheckBox.class, null);
+ table.addContainerProperty("Remove", Button.class, null);
+ table.setImmediate(true);
+ table.setVisible(false);
+ addComponent(table);
+
+ commit = new Button("Save Changes");
+ addComponent(commit);
+ // tabs.addTab(personTab, "Edit Person");
+
+ // tabs.addTab(affiTab, "Edit Affiliation");
+ // addComponent(tabs);
+ }
+
+ public ComboBox getPersonBox() {
+ return person;
+ }
+
+ public ComboBox getOrganizationBox() {
+ return organization;
+ }
+
+ public Button getCommitButton() {
+ return commit;
+ }
+
+ public List getChangedAndNewConnections() {
+ List res = new ArrayList();
+ for (Object affiliationID : table.getItemIds()) {
+ ComboBox roleBox = (ComboBox) table.getItem(affiliationID).getItemProperty("Role").getValue();
+ // String first = (String) table.getItem(id).getItemProperty("First Name").getValue();
+ // String last = (String) table.getItem(id).getItemProperty("Family Name").getValue();
+ // String name = first + " " + last;
+ int personID = personMap.get(currentPerson);
+ String role = "";
+ if (roleBox.getValue() != null)
+ role = (String) roleBox.getValue();
+ res.add(new PersonAffiliationConnectionInfo(personID, (int) affiliationID, role));
+ }
+ return res;
+ }
+
+ public void reactToPersonSelection(List personsWithAffiliations) {
+ table.removeAllItems();
+ personAffiliationsInTable = new HashMap();
+ Person p = personsWithAffiliations.get(0);
+ String title = p.getTitle();
+ String first = p.getFirstName();
+ String last = p.getLastName();
+ currentPerson = first + " " + last;
+ table.setCaption("Affiliations of " + title + " " + first + " " + last);
+ addDataToTable(personsWithAffiliations);
+
+ table.setVisible(true);
+ }
+
+ public void addDataToTable(List personsWithAffiliations) {
+ for (Person p : personsWithAffiliations) {
+ // String title = p.getTitle();
+ // String first = p.getFirst();
+ // String last = p.getLast();
+ Map map = p.getAffiliationInfos();
+ for (Integer i : p.getAffiliationInfos().keySet()) {
+ personAffiliationsInTable.put(i, p);
+ String affiliation = map.get(i).getAffiliation();
+ String role = map.get(i).getRole();
+ List