From 6b53a7e9f59336397f615e4b0a604aef2aff12b0 Mon Sep 17 00:00:00 2001
From: anttil <anttil>
Date: Fri, 23 Sep 2016 11:15:37 +0000
Subject: [PATCH] SSDM-4135: Project samples: Fill in proj_id field in samples
 table using migration

SVN: 37107
---
 .../server/dataaccess/db/DAOFactory.java      | 59 +++++++++++++++++--
 .../generic/shared/dto/ExperimentPE.java      |  2 +
 .../openbis/generic/shared/dto/SamplePE.java  |  6 +-
 3 files changed, 61 insertions(+), 6 deletions(-)

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DAOFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DAOFactory.java
index 40a494b8320..5ccd885e442 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DAOFactory.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DAOFactory.java
@@ -76,6 +76,8 @@ public final class DAOFactory extends AuthorizationDAOFactory implements IDAOFac
 {
     private static Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, DAOFactory.class);
 
+    public static boolean projectSamplesEnabled = false;
+
     static
     {
         SpringEoDSQLExceptionTranslator.activate();
@@ -342,31 +344,78 @@ public final class DAOFactory extends AuthorizationDAOFactory implements IDAOFac
         return operationExecutionDAO;
     }
 
+    private static String projectConstraintFunction =
+            "CREATE FUNCTION check_project_is_defined_for_experiment_level_samples() " +
+                    "  RETURNS trigger AS " +
+                    "$BODY$ " +
+                    "BEGIN " +
+                    "  IF (NEW.proj_id IS NULL AND NEW.expe_id IS NOT NULL) THEN " +
+                    "    RAISE EXCEPTION 'Project has to be defined for experiment level samples'; " +
+                    "  END IF; " +
+                    "  RETURN NEW; " +
+                    "END; " +
+                    "$BODY$ " +
+                    "  LANGUAGE 'plpgsql';";
+
+    private static String projectConstraintTrigger =
+            "CREATE TRIGGER check_project_is_defined_for_experiment_level_samples " +
+                    "BEFORE INSERT OR UPDATE " +
+                    "ON samples_all " +
+                    "FOR EACH ROW " +
+                    "EXECUTE PROCEDURE check_project_is_defined_for_experiment_level_samples();";
+
+    private static String setProjectsToSamplesWithExperiments =
+            "UPDATE samples_all AS s  " +
+                    "SET proj_id = (SELECT proj_id FROM experiments_all WHERE id = s.expe_id) " +
+                    "WHERE s.proj_id IS NULL AND s.expe_id IS NOT NULL;";
+
     @Override
     public void afterPropertiesSet() throws Exception
     {
         Properties serviceProperties = configurer.getResolvedProps();
-        boolean projectSamplesEnabled = PropertyUtils.getBoolean(serviceProperties, Constants.PROJECT_SAMPLES_ENABLED_KEY, false);
+        projectSamplesEnabled = PropertyUtils.getBoolean(serviceProperties, Constants.PROJECT_SAMPLES_ENABLED_KEY, false);
         Connection connection = null;
         try
         {
             connection = context.getDataSource().getConnection();
             Statement statement = connection.createStatement();
+            connection.setAutoCommit(false);
+
+            ResultSet result = statement.executeQuery("SELECT tgname FROM pg_trigger WHERE tgname='disable_project_level_samples'");
+            boolean triggerExists = result.next();
+
             if (projectSamplesEnabled)
             {
-                operationLog.info("Enable project samples by dropping the trigger 'disable_project_level_samples'.");
-                statement.executeUpdate("DROP TRIGGER IF EXISTS disable_project_level_samples ON samples_all");
+                if (triggerExists)
+                {
+                    operationLog.info("Enable project samples by dropping the trigger 'disable_project_level_samples'.");
+                    statement.executeUpdate("DROP TRIGGER disable_project_level_samples ON samples_all");
+
+                    statement.executeUpdate(projectConstraintFunction);
+                    statement.executeUpdate(projectConstraintTrigger);
+                    statement.executeUpdate(setProjectsToSamplesWithExperiments);
+                } else
+                {
+                    operationLog.info("Project samples already enabled.");
+                }
             } else
             {
-                ResultSet result = statement.executeQuery("SELECT tgname FROM pg_trigger WHERE tgname='disable_project_level_samples'");
-                boolean triggerExists = result.next();
                 if (triggerExists == false)
                 {
                     operationLog.warn("It is not possible to disable project samples feature. The system still considers "
                             + Constants.PROJECT_SAMPLES_ENABLED_KEY + "=true.");
+                    projectSamplesEnabled = true;
                 }
             }
             statement.close();
+            connection.commit();
+        } catch (Throwable t)
+        {
+            operationLog.info("Failed to enable project level samples.", t);
+            if (connection != null)
+            {
+                connection.rollback();
+            }
         } finally
         {
             if (connection != null)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentPE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentPE.java
index 2708e8fa6bd..219191c9cc6 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentPE.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentPE.java
@@ -396,6 +396,7 @@ public class ExperimentPE extends AttachmentHolderPE implements
     {
         getExperimentSamples().remove(sample);
         sample.setExperimentInternal(null);
+        sample.setProject(null);
     }
 
     public void addSample(SamplePE sample)
@@ -406,6 +407,7 @@ public class ExperimentPE extends AttachmentHolderPE implements
             experiment.getExperimentSamples().remove(sample);
         }
         sample.setExperimentInternal(this);
+        sample.setProject(project);
         getExperimentSamples().add(sample);
     }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SamplePE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SamplePE.java
index f5852f45764..bef26aa7cea 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SamplePE.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SamplePE.java
@@ -69,6 +69,7 @@ import org.hibernate.validator.constraints.Length;
 
 import ch.systemsx.cisd.common.collection.UnmodifiableSetDecorator;
 import ch.systemsx.cisd.common.reflection.ModifiedShortPrefixToStringStyle;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.db.DAOFactory;
 import ch.systemsx.cisd.openbis.generic.shared.IServer;
 import ch.systemsx.cisd.openbis.generic.shared.basic.BasicConstant;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IIdentityHolder;
@@ -490,7 +491,10 @@ public class SamplePE extends AttachmentHolderPE implements IIdAndCodeHolder, Co
 
     public void setProject(ProjectPE project)
     {
-        this.project = project;
+        if (DAOFactory.projectSamplesEnabled)
+        {
+            this.project = project;
+        }
     }
 
     @ManyToOne(fetch = FetchType.LAZY)
-- 
GitLab