From b3e5cee6900caca043ffcf7976b1f3051ee26df4 Mon Sep 17 00:00:00 2001
From: buczekp <buczekp>
Date: Fri, 6 Aug 2010 14:41:41 +0000
Subject: [PATCH] [LMS-1676] initial changes in sample update; small
 refactoring

SVN: 17355
---
 .../bo/AbstractSampleBusinessObject.java      | 76 +++++++++++++++----
 .../server/business/bo/ExperimentBO.java      | 15 +---
 .../generic/server/business/bo/SampleBO.java  | 58 ++++++++++++++
 .../shared/basic/dto/BasicSampleUpdates.java  | 19 +++++
 .../generic/shared/basic/dto/Code.java        |  5 ++
 .../DataStoreServiceTranslator.java           | 21 +----
 .../ExperimentPlateLocationsSection.java      | 13 +---
 .../server/logic/PlateContentLoader.java      | 13 +---
 8 files changed, 153 insertions(+), 67 deletions(-)

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractSampleBusinessObject.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractSampleBusinessObject.java
index 291ba705c57..f7f40c9d9d7 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractSampleBusinessObject.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractSampleBusinessObject.java
@@ -192,28 +192,76 @@ abstract class AbstractSampleBusinessObject extends AbstractSampleIdentifierBusi
     protected void setGeneratedFrom(final SampleIdentifier sampleIdentifier,
             final SamplePE samplePE, String parentIdentifier)
     {
-        for (SampleRelationshipPE r : samplePE.getParentRelationships())
+        removeParents(samplePE);
+        final SamplePE parentPE = tryGetValidSample(parentIdentifier, sampleIdentifier);
+        if (parentPE != null)
+        {
+            RelationshipTypePE relationship = tryFindParentChildRelationshipType();
+            samplePE.addParentRelationship(new SampleRelationshipPE(parentPE, samplePE,
+                    relationship));
+        }
+    }
+
+    protected void setParents(SamplePE child, List<SamplePE> parents)
+    {
+        removeParents(child);
+        RelationshipTypePE relationshipType = tryFindParentChildRelationshipType();
+        for (SamplePE parent : parents)
+        {
+            addParentRelationship(child, parent, relationshipType);
+        }
+    }
+
+    private void removeParents(SamplePE child)
+    {
+        for (SampleRelationshipPE r : child.getParentRelationships())
         {
             if (r.getRelationship().getCode().equals(
                     BasicConstant.PARENT_CHILD_INTERNAL_RELATIONSHIP))
             {
-                samplePE.removeParentRelationship(r);
+                child.removeParentRelationship(r);
             }
         }
-        final SamplePE parentPE = tryGetValidSample(parentIdentifier, sampleIdentifier);
-        if (parentPE != null)
+    }
+
+    // ineffective for adding a collection of parents
+    protected void addParent(SamplePE child, SamplePE parent)
+    {
+        RelationshipTypePE relationshipType = tryFindParentChildRelationshipType();
+        addParentRelationship(child, parent, relationshipType);
+    }
+
+    protected void addParents(SamplePE child, List<SamplePE> parents)
+    {
+        RelationshipTypePE relationshipType = tryFindParentChildRelationshipType();
+        for (SamplePE parent : parents)
         {
-            RelationshipTypePE relationship =
-                    getRelationshipTypeDAO().tryFindRelationshipTypeByCode(
-                            BasicConstant.PARENT_CHILD_INTERNAL_RELATIONSHIP);
-            if (relationship == null)
-            {
-                throw new UserFailureException(
-                        "'Parent - Child' relationship definition could not be found.");
-            }
-            samplePE.addParentRelationship(new SampleRelationshipPE(parentPE, samplePE,
-                    relationship));
+            addParentRelationship(child, parent, relationshipType);
+        }
+    }
+
+    private void addParentRelationship(SamplePE child, SamplePE parent,
+            RelationshipTypePE relationshipType)
+    {
+        final SampleRelationshipPE relationship =
+                new SampleRelationshipPE(child, parent, relationshipType);
+        child.addParentRelationship(relationship);
+    }
+
+    protected RelationshipTypePE tryFindParentChildRelationshipType()
+    {
+        return tryFindRelationshipTypeByCode(BasicConstant.PARENT_CHILD_INTERNAL_RELATIONSHIP);
+    }
+
+    protected RelationshipTypePE tryFindRelationshipTypeByCode(String code)
+    {
+        RelationshipTypePE result = getRelationshipTypeDAO().tryFindRelationshipTypeByCode(code);
+        if (result == null)
+        {
+            throw UserFailureException.fromTemplate(
+                    "'%s' relationship definition could not be found.", code);
         }
+        return result;
     }
 
     private SamplePE tryGetValidSample(final String parentIdentifierOrNull,
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExperimentBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExperimentBO.java
index c5c92256fdc..5c2d9d823da 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExperimentBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExperimentBO.java
@@ -32,6 +32,7 @@ import ch.systemsx.cisd.openbis.generic.server.dataaccess.IAttachmentDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.ISampleDAO;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Code;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewExperiment;
@@ -443,7 +444,7 @@ public final class ExperimentBO extends AbstractBusinessObject implements IExper
     void setExperimentSamples(String[] sampleCodes)
     {
         List<SamplePE> samples = experiment.getSamples();
-        String[] currentSampleCodes = extractCodes(samples);
+        String[] currentSampleCodes = Code.extractCodesToArray(samples);
         Set<String> currentSampleCodesSet = asSet(currentSampleCodes);
         Set<String> codesToAdd = asSet(sampleCodes);
         codesToAdd.removeAll(currentSampleCodesSet);
@@ -537,18 +538,6 @@ public final class ExperimentBO extends AbstractBusinessObject implements IExper
         return new HashSet<String>(Arrays.asList(objects));
     }
 
-    private static String[] extractCodes(List<SamplePE> samples)
-    {
-        String[] codes = new String[samples.size()];
-        int i = 0;
-        for (SamplePE sample : samples)
-        {
-            codes[i] = sample.getCode();
-            i++;
-        }
-        return codes;
-    }
-
     @Private
     void updateProject(ProjectIdentifier newProjectIdentifier)
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleBO.java
index 2448908f521..7bcf3e78466 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleBO.java
@@ -17,16 +17,20 @@
 package ch.systemsx.cisd.openbis.generic.server.business.bo;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
 import org.springframework.dao.DataAccessException;
 import org.springframework.dao.DataIntegrityViolationException;
 
+import ch.systemsx.cisd.common.collections.CollectionUtils;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.util.SampleUtils;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IAttachmentDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.ISampleDAO;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
@@ -34,6 +38,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
 import ch.systemsx.cisd.openbis.generic.shared.dto.AttachmentPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.GroupPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePropertyPE;
@@ -238,12 +243,14 @@ public final class SampleBO extends AbstractSampleBusinessObject implements ISam
         updateProperties(updates.getProperties());
         updateGroup(sample, updates.getSampleIdentifier(), null);
         updateExperiment(sample, updates.getExperimentIdentifierOrNull(), null);
+        // TODO 2010-08-06, Piotr Buczek: get rid of this
         setGeneratedFrom(updates.getSampleIdentifier(), sample, updates.getParentIdentifierOrNull());
         setContainer(updates.getSampleIdentifier(), sample, updates.getContainerIdentifierOrNull());
         for (NewAttachment attachment : updates.getAttachments())
         {
             addAttachment(AttachmentTranslator.translate(attachment));
         }
+        updateParents(updates);
         dataChanged = true;
     }
 
@@ -256,6 +263,56 @@ public final class SampleBO extends AbstractSampleBusinessObject implements ISam
                 properties, registrator));
     }
 
+    private void updateParents(SampleUpdatesDTO updates)
+    {
+        String[] parentCodes = updates.getModifiedParentCodesOrNull();
+        if (parentCodes != null)
+        {
+            attachParents(parentCodes);
+        }
+    }
+
+    // attaches specified existing samples to the sample as parents
+    private void attachParents(String[] parentCodes)
+    {
+        List<SamplePE> parents =
+                findSamplesByCodes(getSampleDAO(), asSet(parentCodes), sample.getGroup());
+        setParents(sample, parents);
+    }
+
+    // Finds samples in the specified group. Throws exception if some samples do not exist.
+    private static List<SamplePE> findSamplesByCodes(ISampleDAO sampleDAO, Set<String> sampleCodes,
+            GroupPE group)
+    {
+        List<SamplePE> samples = new ArrayList<SamplePE>();
+        List<String> missingSamples = new ArrayList<String>();
+        for (String code : sampleCodes)
+        {
+            SamplePE sample = sampleDAO.tryFindByCodeAndGroup(code, group);
+            if (sample == null)
+            {
+                missingSamples.add(code);
+            } else
+            {
+                samples.add(sample);
+            }
+        }
+        if (missingSamples.size() > 0)
+        {
+            throw UserFailureException.fromTemplate(
+                    "Samples with following codes do not exist in the space '%s': '%s'.", group
+                            .getCode(), CollectionUtils.abbreviate(missingSamples, 10));
+        } else
+        {
+            return samples;
+        }
+    }
+
+    private static Set<String> asSet(String[] objects)
+    {
+        return new HashSet<String>(Arrays.asList(objects));
+    }
+
     public void setGeneratedCode()
     {
         final String code = createCode(EntityKind.SAMPLE);
@@ -327,4 +384,5 @@ public final class SampleBO extends AbstractSampleBusinessObject implements ISam
             HibernateUtils.initialize(sample.getProperties());
         }
     }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/BasicSampleUpdates.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/BasicSampleUpdates.java
index 142d32a5697..84552fab3aa 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/BasicSampleUpdates.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/BasicSampleUpdates.java
@@ -39,10 +39,18 @@ public class BasicSampleUpdates implements IsSerializable, Serializable
 
     private Date version;
 
+    // TODO 2010-08-06, Piotr Buczek: get rid of this
     private String parentIdentifierOrNull;
 
     private String containerIdentifierOrNull;
 
+    // New set of parent sample codes which will replace the old ones. In this way some
+    // parent samples can be unassigned and some assigned as a result. It will be assumed that
+    // all the samples belong to the same group as the child sample.
+    // If equals to null nothing should be changed.
+    // If some previously assigned parent sample is missing on this list, it will be unassigned.
+    private String[] modifiedParentCodesOrNull;
+
     public String getParentIdentifierOrNull()
     {
         return parentIdentifierOrNull;
@@ -107,4 +115,15 @@ public class BasicSampleUpdates implements IsSerializable, Serializable
         this.version = version;
     }
 
+    // if null nothing should be changed
+    public String[] getModifiedParentCodesOrNull()
+    {
+        return modifiedParentCodesOrNull;
+    }
+
+    public void setModifiedParentCodesOrNull(String[] modifiedParentCodesOrNull)
+    {
+        this.modifiedParentCodesOrNull = modifiedParentCodesOrNull;
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Code.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Code.java
index db5d97ccdf6..56ae7fd4190 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Code.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Code.java
@@ -113,6 +113,11 @@ public class Code<T extends Code<T>> implements IsSerializable, ICodeHolder, Com
         return codes;
     }
 
+    public final static String[] extractCodesToArray(Collection<? extends ICodeHolder> codeProviders)
+    {
+        return extractCodes(codeProviders).toArray(new String[codeProviders.size()]);
+    }
+
     public final static class CodeProviderComparator implements Comparator<ICodeHolder>,
             Serializable
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/DataStoreServiceTranslator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/DataStoreServiceTranslator.java
index cac64364708..5c63c1f09f1 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/DataStoreServiceTranslator.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/DataStoreServiceTranslator.java
@@ -16,22 +16,20 @@
 
 package ch.systemsx.cisd.openbis.generic.shared.translator;
 
-import java.util.Set;
-
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Code;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatastoreServiceDescription;
-import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DataStoreServicePE;
 
 /**
  * Translator for {@link DataStoreServicePE} into {@link DatastoreServiceDescription}.
- *
+ * 
  * @author Franz-Josef Elmer
  */
 public class DataStoreServiceTranslator
 {
     public static DatastoreServiceDescription translate(DataStoreServicePE service)
     {
-        String[] datasetTypeCodes = extractCodes(service.getDatasetTypes());
+        String[] datasetTypeCodes = Code.extractCodesToArray(service.getDatasetTypes());
         String dssCode = service.getDataStore().getCode();
         DatastoreServiceDescription dssDescription =
                 new DatastoreServiceDescription(service.getKey(), service.getLabel(),
@@ -40,19 +38,6 @@ public class DataStoreServiceTranslator
         return dssDescription;
     }
 
-    private static String[] extractCodes(Set<DataSetTypePE> datasetTypes)
-    {
-        String[] codes = new String[datasetTypes.size()];
-        int i = 0;
-        for (DataSetTypePE datasetType : datasetTypes)
-        {
-            codes[i] = datasetType.getCode();
-            i++;
-        }
-        return codes;
-    }
-
-    
     private DataStoreServiceTranslator()
     {
     }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/ExperimentPlateLocationsSection.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/ExperimentPlateLocationsSection.java
index a1e9f20ace3..cbf96f2508b 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/ExperimentPlateLocationsSection.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/ExperimentPlateLocationsSection.java
@@ -1,6 +1,5 @@
 package ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.detailviewers;
 
-import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 
@@ -26,6 +25,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.help.HelpP
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.MultilineVarcharField;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.IDisposableComponent;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolderWithIdentifier;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Code;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
 import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.IScreeningClientServiceAsync;
 import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.Dict;
@@ -152,18 +152,9 @@ public class ExperimentPlateLocationsSection extends SingleSectionPanel
         {
             return null;
         }
-        String[] materialTypeCodes = extractCodes(materialTypesOrNull);
+        String[] materialTypeCodes = Code.extractCodesToArray(materialTypesOrNull);
         return PlateMaterialReviewer.create(screeningViewContext, experiment, materialItemList,
                 materialTypeCodes);
     }
 
-    private static String[] extractCodes(List<MaterialType> materialTypes)
-    {
-        List<String> codes = new ArrayList<String>();
-        for (MaterialType type : materialTypes)
-        {
-            codes.add(type.getCode());
-        }
-        return codes.toArray(new String[0]);
-    }
 }
\ No newline at end of file
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/PlateContentLoader.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/PlateContentLoader.java
index 150adfba1f4..f96eda9cfd6 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/PlateContentLoader.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/PlateContentLoader.java
@@ -25,6 +25,7 @@ import ch.systemsx.cisd.openbis.generic.server.business.bo.IExternalDataTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.samplelister.ISampleLister;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Code;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListOrSearchSampleCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
@@ -151,7 +152,7 @@ public class PlateContentLoader
     {
         List<ExternalDataPE> analysisDatasets =
                 ScreeningUtils.filterImageAnalysisDatasets(datasets);
-        List<String> datasetCodes = extractCodes(analysisDatasets);
+        List<String> datasetCodes = Code.extractCodes(analysisDatasets);
         String dataStoreCode = extractDataStoreCode(analysisDatasets);
         return DatasetReportsLoader.loadAnalysisResults(datasetCodes, dataStoreCode,
                 externalDataTable);
@@ -165,16 +166,6 @@ public class PlateContentLoader
         return dataStoreCode;
     }
 
-    private List<String> extractCodes(List<ExternalDataPE> datasets)
-    {
-        List<String> datasetCodes = new ArrayList<String>();
-        for (ExternalDataPE dataset : datasets)
-        {
-            datasetCodes.add(dataset.getCode());
-        }
-        return datasetCodes;
-    }
-
     private String extractDataStoreCode(ExternalDataPE imageDataset)
     {
         return imageDataset.getDataStore().getCode();
-- 
GitLab