From e159f4819d3d0f75f62749b4b5476a9470cb786a Mon Sep 17 00:00:00 2001
From: buczekp <buczekp>
Date: Tue, 26 Oct 2010 21:39:17 +0000
Subject: [PATCH] [LMS-1845] reevaluation of dynamic properties after modifying
 a script or exchanging the script used in assignment with a different one

SVN: 18451
---
 .../business/bo/EntityTypePropertyTypeBO.java | 19 +++--
 .../generic/server/business/bo/ScriptBO.java  | 17 +++-
 .../dataaccess/IEntityPropertyTypeDAO.java    |  4 +
 .../dataaccess/db/EntityPropertyTypeDAO.java  | 11 +++
 .../DefaultDynamicPropertyEvaluator.java      | 12 +--
 .../generic/shared/dto/DataSetTypePE.java     |  8 ++
 .../generic/shared/dto/EntityTypePE.java      |  6 +-
 .../shared/dto/EntityTypePropertyTypePE.java  |  2 +-
 .../generic/shared/dto/ExperimentTypePE.java  |  7 ++
 .../generic/shared/dto/MaterialTypePE.java    |  8 ++
 .../generic/shared/dto/SampleTypePE.java      |  8 ++
 .../openbis/generic/shared/dto/ScriptPE.java  | 85 +++++++++++++++++++
 12 files changed, 172 insertions(+), 15 deletions(-)

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityTypePropertyTypeBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityTypePropertyTypeBO.java
index 38040bb3a36..45f38d244fc 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityTypePropertyTypeBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityTypePropertyTypeBO.java
@@ -226,18 +226,25 @@ public class EntityTypePropertyTypeBO extends AbstractBusinessObject implements
         assignment.setMandatory(assignmentUpdates.isMandatory());
         if (assignmentUpdates.isDynamic() != assignment.isDynamic())
         {
-            throw new UserFailureException(
-                    String.format(
-                            "Changing assignment from '%s' to '%s' is not allowed. Please create a new assignment.",
-                            describeDynamic(assignment.isDynamic()),
-                            describeDynamic(assignmentUpdates.isDynamic())));
+            throw new UserFailureException(String.format(
+                    "Changing assignment from '%s' to '%s' is not allowed. "
+                            + "Please create a new assignment.",
+                    describeDynamic(assignment.isDynamic()),
+                    describeDynamic(assignmentUpdates.isDynamic())));
         }
-        if (assignment.isDynamic())
+        boolean scriptChanged = false;
+        if (assignment.isDynamic()
+                && assignment.getScript().getName().equals(assignmentUpdates.getScriptName()) == false)
         {
+            scriptChanged = true;
             ScriptPE script = getScriptDAO().tryFindByName(assignmentUpdates.getScriptName());
             assignment.setScript(script);
         }
         validateAndSave();
+        if (scriptChanged)
+        {
+            getEntityPropertyTypeDAO(entityKind).scheduleDynamicPropertiesEvaluation(assignment);
+        }
     }
 
     private static String describeDynamic(boolean dynamic)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ScriptBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ScriptBO.java
index 2d77b80e383..e05eaa95623 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ScriptBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ScriptBO.java
@@ -24,6 +24,7 @@ import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IScriptUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Script;
+import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePropertyTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ScriptPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 
@@ -94,7 +95,21 @@ public final class ScriptBO extends AbstractBusinessObject implements IScriptBO
         loadDataByTechId(TechId.create(updates));
         script.setName(updates.getName());
         script.setDescription(updates.getDescription());
-        script.setScript(updates.getScript());
+        boolean scriptChanged = false;
+        if (script.getScript().equals(updates.getScript()) == false)
+        {
+            scriptChanged = true;
+            script.setScript(updates.getScript());
+        }
         getScriptDAO().createOrUpdate(script);
+        if (scriptChanged)
+        {
+            for (EntityTypePropertyTypePE assignment : script.getPropertyAssignments())
+            {
+                getEntityPropertyTypeDAO(assignment.getEntityType().getEntityKind())
+                        .scheduleDynamicPropertiesEvaluation(assignment);
+            }
+        }
     }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IEntityPropertyTypeDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IEntityPropertyTypeDAO.java
index fec87ebf619..f0d5eff7e70 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IEntityPropertyTypeDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IEntityPropertyTypeDAO.java
@@ -79,6 +79,10 @@ public interface IEntityPropertyTypeDAO
     public List<Long> listIdsOfEntitiesWithoutPropertyValue(
             final EntityTypePropertyTypePE assignment) throws DataAccessException;
 
+    /** Schedules evaluation of dynamic properties */
+    public void scheduleDynamicPropertiesEvaluation(final EntityTypePropertyTypePE assignment)
+            throws DataAccessException;
+
     /**
      * Fills term usage statistics for the entity kind represented by this class.
      * 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/EntityPropertyTypeDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/EntityPropertyTypeDAO.java
index ab23558ca4f..bc5006527ef 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/EntityPropertyTypeDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/EntityPropertyTypeDAO.java
@@ -174,6 +174,17 @@ final class EntityPropertyTypeDAO extends AbstractDAO implements IEntityProperty
         return list;
     }
 
+    public void scheduleDynamicPropertiesEvaluation(final EntityTypePropertyTypePE assignment)
+            throws DataAccessException
+    {
+        assert assignment != null : "Unspecified assignment.";
+        if (assignment.isDynamic()) // sanity check
+        {
+            List<Long> entityIds = listEntityIds(assignment);
+            scheduleDynamicPropertiesEvaluation(entityIds);
+        }
+    }
+
     private List<Long> listEntityIds(final EntityTypePropertyTypePE assignment)
             throws DataAccessException
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/dynamic_property/DefaultDynamicPropertyEvaluator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/dynamic_property/DefaultDynamicPropertyEvaluator.java
index b3a853c6e22..84376c95046 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/dynamic_property/DefaultDynamicPropertyEvaluator.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/dynamic_property/DefaultDynamicPropertyEvaluator.java
@@ -120,13 +120,13 @@ final class DefaultDynamicPropertyEvaluator implements IDynamicPropertyEvaluator
                         listEntitiesWithRestrictedId(hibernateSession, clazz, minId, maxId);
                 evaluateProperties(hibernateSession, results, clazz);
                 index = nextIndex;
-                operationLog.info(String.format("%d/%d %ss have been updated...", index, maxIndex,
-                        clazz.getSimpleName()));
+                operationLog.info(String.format("%d/%d %ss have been updated...", index + 1,
+                        maxIndex + 1, clazz.getSimpleName()));
             }
             transaction.commit();
             operationLog.info(String.format(
                     "Evaluation of dynamic properties for '%s' is complete. "
-                            + "%d entities have been updated.", clazz.getSimpleName(), index));
+                            + "%d entities have been updated.", clazz.getSimpleName(), index + 1));
             return ids;
         } catch (Exception e)
         {
@@ -166,13 +166,13 @@ final class DefaultDynamicPropertyEvaluator implements IDynamicPropertyEvaluator
                         listEntitiesWithRestrictedId(hibernateSession, clazz, subList);
                 evaluateProperties(hibernateSession, results, clazz);
                 index = nextIndex;
-                operationLog.info(String.format("%d/%d %ss have been updated...", index + 1,
-                        maxIndex + 1, clazz.getSimpleName()));
+                operationLog.info(String.format("%d/%d %ss have been updated...", index, maxIndex,
+                        clazz.getSimpleName()));
             }
             transaction.commit();
             operationLog.info(String.format(
                     "Evaluation of dynamic properties for '%s' is complete. "
-                            + "%d entities have been updated.", clazz.getSimpleName(), index + 1));
+                            + "%d entities have been updated.", clazz.getSimpleName(), index));
             return dynamicIds;
         } catch (Exception e)
         {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataSetTypePE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataSetTypePE.java
index 7dadbaa6603..58893a6134f 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataSetTypePE.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataSetTypePE.java
@@ -37,6 +37,7 @@ import org.hibernate.validator.Length;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericConstants;
 import ch.systemsx.cisd.openbis.generic.shared.IServer;
+import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
 
 /**
  * Persistence Entity representing data set type.
@@ -131,4 +132,11 @@ public class DataSetTypePE extends EntityTypePE
     {
         this.mainDataSetPattern = mainDataSetPattern;
     }
+
+    @Override
+    @Transient
+    public EntityKind getEntityKind()
+    {
+        return EntityKind.DATA_SET;
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/EntityTypePE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/EntityTypePE.java
index 1ee963a6296..e7eb52ee292 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/EntityTypePE.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/EntityTypePE.java
@@ -20,6 +20,7 @@ import javax.persistence.FetchType;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
 import javax.persistence.MappedSuperclass;
+import javax.persistence.Transient;
 
 import org.apache.commons.lang.builder.EqualsBuilder;
 import org.apache.commons.lang.builder.HashCodeBuilder;
@@ -37,7 +38,7 @@ import ch.systemsx.cisd.openbis.generic.shared.util.EqualsHashUtils;
  * Entity is one of: material, sample, experiment
  * </p>
  * 
- * @author     Franz-Josef Elmer
+ * @author Franz-Josef Elmer
  * @author Izabela Adamczyk
  */
 @MappedSuperclass
@@ -45,6 +46,9 @@ public abstract class EntityTypePE extends AbstractTypePE
 {
     private static final long serialVersionUID = IServer.VERSION;
 
+    @Transient
+    public abstract EntityKind getEntityKind();
+
     private DatabaseInstancePE databaseInstance;
 
     @ManyToOne(fetch = FetchType.EAGER)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/EntityTypePropertyTypePE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/EntityTypePropertyTypePE.java
index fe6f461df57..f1662adf65b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/EntityTypePropertyTypePE.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/EntityTypePropertyTypePE.java
@@ -125,7 +125,7 @@ public abstract class EntityTypePropertyTypePE extends HibernateAbstractRegistra
     }
 
     @ManyToOne(fetch = FetchType.EAGER)
-    @JoinColumn(name = ColumnNames.SCRIPT_ID_COLUMN)
+    @JoinColumn(name = ColumnNames.SCRIPT_ID_COLUMN, updatable = true)
     public ScriptPE getScript()
     {
         return script;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentTypePE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentTypePE.java
index e29dff09bc0..7ebe91a2b67 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentTypePE.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentTypePE.java
@@ -34,6 +34,7 @@ import javax.persistence.UniqueConstraint;
 import org.hibernate.annotations.Cascade;
 
 import ch.systemsx.cisd.openbis.generic.shared.IServer;
+import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
 
 /**
  * Persistence entity representing type of experiment.
@@ -102,4 +103,10 @@ public final class ExperimentTypePE extends EntityTypePE
         getExperimentTypePropertyTypesInternal().add(child);
     }
 
+    @Override
+    @Transient
+    public EntityKind getEntityKind()
+    {
+        return EntityKind.EXPERIMENT;
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/MaterialTypePE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/MaterialTypePE.java
index d7771c6574c..6b58cea9935 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/MaterialTypePE.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/MaterialTypePE.java
@@ -34,6 +34,7 @@ import javax.persistence.UniqueConstraint;
 import org.hibernate.annotations.Cascade;
 
 import ch.systemsx.cisd.openbis.generic.shared.IServer;
+import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
 
 /**
  * Persistence entity representing type of material.
@@ -105,4 +106,11 @@ public final class MaterialTypePE extends EntityTypePE
         child.setEntityTypeInternal(this);
         getMaterialTypePropertyTypesInternal().add(child);
     }
+
+    @Override
+    @Transient
+    public EntityKind getEntityKind()
+    {
+        return EntityKind.MATERIAL;
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SampleTypePE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SampleTypePE.java
index 502c47f14f4..08245e1c842 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SampleTypePE.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SampleTypePE.java
@@ -39,6 +39,7 @@ import org.hibernate.validator.NotNull;
 import org.hibernate.validator.Pattern;
 
 import ch.systemsx.cisd.openbis.generic.shared.IServer;
+import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
 
 /**
  * Persistence Entity representing 'sample type'.
@@ -206,4 +207,11 @@ public final class SampleTypePE extends EntityTypePE
         return builder;
     }
 
+    @Override
+    @Transient
+    public EntityKind getEntityKind()
+    {
+        return EntityKind.SAMPLE;
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ScriptPE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ScriptPE.java
index 273cdae27a0..e7d27a20cad 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ScriptPE.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ScriptPE.java
@@ -17,6 +17,8 @@
 package ch.systemsx.cisd.openbis.generic.shared.dto;
 
 import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
 
 import javax.persistence.Column;
 import javax.persistence.Entity;
@@ -26,14 +28,17 @@ import javax.persistence.GenerationType;
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
 import javax.persistence.SequenceGenerator;
 import javax.persistence.Table;
+import javax.persistence.Transient;
 
 import org.apache.commons.lang.builder.EqualsBuilder;
 import org.apache.commons.lang.builder.HashCodeBuilder;
 import org.hibernate.validator.Length;
 import org.hibernate.validator.NotNull;
 
+import ch.systemsx.cisd.common.collections.UnmodifiableListDecorator;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericConstants;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IIdHolder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
@@ -61,6 +66,22 @@ public class ScriptPE extends HibernateAbstractRegistrationHolder implements IId
 
     private String script;
 
+    //
+    // assignments using the script - readonly
+    //
+
+    private List<SampleTypePropertyTypePE> sampleAssignments =
+            new ArrayList<SampleTypePropertyTypePE>();
+
+    private List<ExperimentTypePropertyTypePE> experimentAssignments =
+            new ArrayList<ExperimentTypePropertyTypePE>();
+
+    private List<MaterialTypePropertyTypePE> materialAssignments =
+            new ArrayList<MaterialTypePropertyTypePE>();
+
+    private List<DataSetTypePropertyTypePE> dataSetAssignments =
+            new ArrayList<DataSetTypePropertyTypePE>();
+
     @Column(name = ColumnNames.DESCRIPTION_COLUMN)
     @Length(max = GenericConstants.DESCRIPTION_2000, message = ValidationMessages.DESCRIPTION_LENGTH_MESSAGE)
     public String getDescription()
@@ -172,4 +193,68 @@ public class ScriptPE extends HibernateAbstractRegistrationHolder implements IId
         }
         return thisName.compareTo(thatName);
     }
+
+    //
+    // assignments using the script - readonly
+    //
+
+    @Transient
+    /** all dynamic property assignments using the script */
+    public List<EntityTypePropertyTypePE> getPropertyAssignments()
+    {
+        List<EntityTypePropertyTypePE> assignments = new ArrayList<EntityTypePropertyTypePE>();
+        assignments.addAll(getDataSetAssignments());
+        assignments.addAll(getExperimentAssignments());
+        assignments.addAll(getMaterialAssignments());
+        assignments.addAll(getSampleAssignments());
+        return new UnmodifiableListDecorator<EntityTypePropertyTypePE>(assignments);
+    }
+
+    @OneToMany(fetch = FetchType.LAZY, mappedBy = "script")
+    private List<SampleTypePropertyTypePE> getSampleAssignments()
+    {
+        return sampleAssignments;
+    }
+
+    @SuppressWarnings("unused")
+    private void setSampleAssignments(List<SampleTypePropertyTypePE> sampleAssignments)
+    {
+        this.sampleAssignments = sampleAssignments;
+    }
+
+    @OneToMany(fetch = FetchType.LAZY, mappedBy = "script")
+    private List<ExperimentTypePropertyTypePE> getExperimentAssignments()
+    {
+        return experimentAssignments;
+    }
+
+    @SuppressWarnings("unused")
+    private void setExperimentAssignments(List<ExperimentTypePropertyTypePE> experimentAssignments)
+    {
+        this.experimentAssignments = experimentAssignments;
+    }
+
+    @OneToMany(fetch = FetchType.LAZY, mappedBy = "script")
+    private List<MaterialTypePropertyTypePE> getMaterialAssignments()
+    {
+        return materialAssignments;
+    }
+
+    @SuppressWarnings("unused")
+    private void setMaterialAssignments(List<MaterialTypePropertyTypePE> materialAssignments)
+    {
+        this.materialAssignments = materialAssignments;
+    }
+
+    @OneToMany(fetch = FetchType.LAZY, mappedBy = "script")
+    private List<DataSetTypePropertyTypePE> getDataSetAssignments()
+    {
+        return dataSetAssignments;
+    }
+
+    @SuppressWarnings("unused")
+    private void setDataListAssignments(List<DataSetTypePropertyTypePE> dataSetAssignments)
+    {
+        this.dataSetAssignments = dataSetAssignments;
+    }
 }
-- 
GitLab