From 1f0948d0550b395c975c86ba0eea41f4209426d0 Mon Sep 17 00:00:00 2001
From: jakubs <jakubs>
Date: Fri, 27 Jan 2012 16:08:24 +0000
Subject: [PATCH] LMS-2738 DSS robustness - add setStorageConfirmation method
 to ExternalData, and expose it through ETLService

SVN: 24298
---
 .../openbis/generic/server/ETLService.java    |  11 +
 .../generic/server/ETLServiceLogger.java      |   5 +
 .../generic/server/business/bo/DataBO.java    |  18 +
 .../generic/server/business/bo/IDataBO.java   |   8 +
 .../server/dataaccess/db/ExternalDataDAO.java | 554 ------------------
 .../generic/shared/IETLLIMSService.java       |   8 +
 .../generic/shared/dto/ExternalDataPE.java    |   2 +-
 .../generic/server/ETLServiceTest.java        |   7 +
 .../server/business/bo/DataBOTest.java        |  12 +
 .../shared/IETLLIMSService.java.expected      |   8 +
 10 files changed, 78 insertions(+), 555 deletions(-)
 delete mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExternalDataDAO.java

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLService.java
index 97f600f372d..536e4538a85 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLService.java
@@ -1494,4 +1494,15 @@ public class ETLService extends AbstractCommonServer<IETLLIMSService> implements
         return trustedOriginDomainProvider.getTrustedDomains();
     }
 
+    public void setStorageConfirmed(String sessionToken, String dataSetCode)
+    {
+        assert sessionToken != null : "Unspecified session token.";
+
+        final Session session = getSession(sessionToken);
+
+        final IDataBO dataBO = businessObjectFactory.createDataBO(session);
+
+        dataBO.loadByCode(dataSetCode);
+        dataBO.setStorageConfirmed();
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceLogger.java
index 663f2578cac..5a660f9548a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceLogger.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceLogger.java
@@ -527,4 +527,9 @@ public class ETLServiceLogger extends AbstractServerLogger implements IETLLIMSSe
         logAccess(sessionToken, "getTrustedCrossOriginDomains");
         return null;
     }
+
+    public void setStorageConfirmed(String sessionToken, String dataSetCode)
+    {
+        logAccess(sessionToken, "setStorageConfirmed", "DATA_SET_CODE(%s)", dataSetCode);
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataBO.java
index 5ce11efde0e..82c4d092b83 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataBO.java
@@ -902,4 +902,22 @@ public class DataBO extends AbstractDataSetBusinessObject implements IDataBO
                 type, managedProperty, registrator));
     }
 
+    public void setStorageConfirmed()
+    {
+        boolean confirmationSuceeded = false;
+        ExternalDataPE externalData = data.tryAsExternalData();
+        if (null != externalData)
+        {
+            externalData.setStorageConfirmation(true);
+            confirmationSuceeded = true;
+        }
+
+        if (false == confirmationSuceeded)
+        {
+            throw new UserFailureException(
+                    String.format(
+                            "Couldn't set the storageConfirmation for dataset %s. It is not an external data.",
+                            data.getCode()));
+        }
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IDataBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IDataBO.java
index 42631ea009d..88b13381402 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IDataBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IDataBO.java
@@ -128,4 +128,12 @@ public interface IDataBO extends IEntityBusinessObject
      */
     public void setContainedDataSets(ExperimentPE experiment, NewContainerDataSet newData);
 
+    /**
+     * Indicate that the storage of the external data has been confirmed.
+     * 
+     * @throws UserFailureException
+     *             if the this is not external data
+     */
+    public void setStorageConfirmed();
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExternalDataDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExternalDataDAO.java
deleted file mode 100644
index 51281744b2f..00000000000
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExternalDataDAO.java
+++ /dev/null
@@ -1,554 +0,0 @@
-/*
- * Copyright 2008 ETH Zuerich, CISD
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package ch.systemsx.cisd.openbis.generic.server.dataaccess.db;
-
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
-
-import org.apache.log4j.Logger;
-import org.hibernate.FetchMode;
-import org.hibernate.HibernateException;
-import org.hibernate.LockMode;
-import org.hibernate.Session;
-import org.hibernate.criterion.Criterion;
-import org.hibernate.criterion.DetachedCriteria;
-import org.hibernate.criterion.Projections;
-import org.hibernate.criterion.Restrictions;
-import org.springframework.dao.DataAccessException;
-import org.springframework.dao.DataIntegrityViolationException;
-import org.springframework.orm.hibernate3.HibernateCallback;
-import org.springframework.orm.hibernate3.HibernateTemplate;
-
-import ch.systemsx.cisd.common.exceptions.UserFailureException;
-import ch.systemsx.cisd.common.logging.LogCategory;
-import ch.systemsx.cisd.common.logging.LogFactory;
-import ch.systemsx.cisd.common.utilities.MethodUtils;
-import ch.systemsx.cisd.openbis.generic.server.dataaccess.IExternalDataDAO;
-import ch.systemsx.cisd.openbis.generic.server.dataaccess.PersistencyResources;
-import ch.systemsx.cisd.openbis.generic.shared.basic.CodeConverter;
-import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolder;
-import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetArchivingStatus;
-import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE;
-import ch.systemsx.cisd.openbis.generic.shared.dto.DataStorePE;
-import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE;
-import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE;
-import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalDataPE;
-import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
-import ch.systemsx.cisd.openbis.generic.shared.dto.TableNames;
-import ch.systemsx.cisd.openbis.generic.shared.util.HibernateUtils;
-
-/**
- * Implementation of IExternalDataDAO for databases.
- * 
- * @author Christian Ribeaud
- */
-@SuppressWarnings("deprecation")
-final class ExternalDataDAO extends AbstractGenericEntityWithPropertiesDAO<ExternalDataPE>
-        implements IExternalDataDAO
-{
-    private final static Class<ExternalDataPE> ENTITY_CLASS = ExternalDataPE.class;
-
-    private final static Class<DataPE> ENTITY_SUPER_CLASS = DataPE.class;
-
-    private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION,
-            ExternalDataDAO.class);
-
-    private static final String TABLE_NAME = ENTITY_CLASS.getSimpleName();
-
-    ExternalDataDAO(final PersistencyResources persistencyResources,
-            final DatabaseInstancePE databaseInstance)
-    {
-        super(persistencyResources, databaseInstance, ENTITY_CLASS);
-    }
-
-    //
-    // IExternalDataDAO
-    //
-
-    public boolean hasExternalData(SamplePE sample) throws DataAccessException
-    {
-        final DetachedCriteria criteria = DetachedCriteria.forClass(ExternalDataPE.class);
-        criteria.add(Restrictions.eq("sampleInternal", sample));
-        criteria.setProjection(Projections.rowCount());
-        Integer count = (Integer) getHibernateTemplate().findByCriteria(criteria).get(0);
-        return count > 0;
-    }
-
-    public final List<ExternalDataPE> listRelatedExternalData(final IEntityInformationHolder entity)
-            throws DataAccessException
-    {
-        assert entity != null : "Unspecified entity.";
-
-        final String entityName = entity.getEntityKind().toString().toLowerCase();
-        final String query =
-                String.format("from %s e " + "left join fetch e.experimentInternal "
-                        + "left join fetch e.sampleInternal " + "left join fetch e.parents "
-                        + "left join fetch e.dataSetProperties " + "where e.%sInternal.id = ?",
-                        TABLE_NAME, entityName);
-        final List<ExternalDataPE> list =
-                cast(getHibernateTemplate().find(query, toArray(entity.getId())));
-
-        // distinct does not work properly in HQL for left joins
-        distinct(list);
-        if (operationLog.isDebugEnabled())
-        {
-            operationLog.debug(String.format("%d external data have been found for [entity=%s].",
-                    list.size(), entity));
-        }
-        return list;
-    }
-
-    public final List<ExternalDataPE> listExternalData(final SamplePE sample)
-            throws DataAccessException
-    {
-        assert sample != null : "Unspecified sample.";
-
-        final String query =
-                String.format("from %s e " + "left join fetch e.experimentInternal "
-                        + "left join fetch e.parents " + "left join fetch e.dataSetProperties "
-                        + "where e.sampleInternal = ?", TABLE_NAME);
-        final List<ExternalDataPE> list = cast(getHibernateTemplate().find(query, toArray(sample)));
-
-        // distinct does not work properly in HQL for left joins
-        distinct(list);
-        if (operationLog.isDebugEnabled())
-        {
-            operationLog.debug(String.format("%d external data have been found for [sample=%s].",
-                    list.size(), sample));
-        }
-        return list;
-    }
-
-    public final List<ExternalDataPE> listExternalData(final DataStorePE dataStore)
-            throws DataAccessException
-    {
-        assert dataStore != null : "Unspecified data store.";
-        final DetachedCriteria criteria = DetachedCriteria.forClass(ExternalDataPE.class);
-        criteria.add(Restrictions.eq("dataStore", dataStore));
-        final List<ExternalDataPE> list = cast(getHibernateTemplate().findByCriteria(criteria));
-        if (operationLog.isDebugEnabled())
-        {
-            operationLog.debug(String.format("%s(%s): %d data set(s) have been found.", MethodUtils
-                    .getCurrentMethod().getName(), dataStore, list.size()));
-        }
-        return list;
-    }
-
-    public final List<ExternalDataPE> listExternalData(final ExperimentPE experiment)
-            throws DataAccessException
-    {
-        assert experiment != null : "Unspecified experiment.";
-
-        final String query =
-                String.format("from %s e " + "left join fetch e.experimentInternal "
-                        + "left join fetch e.parents " + "left join fetch e.dataSetProperties "
-                        + "where e.experimentInternal = ?", TABLE_NAME);
-        final List<ExternalDataPE> list =
-                cast(getHibernateTemplate().find(query, toArray(experiment)));
-
-        // distinct does not work properly in HQL for left joins
-        distinct(list);
-        if (operationLog.isDebugEnabled())
-        {
-            operationLog.debug(String.format(
-                    "%d external data have been found for [experiment=%s].", list.size(),
-                    experiment));
-        }
-        return list;
-    }
-
-    private void distinct(List<ExternalDataPE> list)
-    {
-        Set<ExternalDataPE> set = new TreeSet<ExternalDataPE>(list);
-        list.clear();
-        list.addAll(set);
-    }
-
-    public DataPE tryToFindDataSetByCode(String dataSetCode)
-    {
-        assert dataSetCode != null : "Unspecified data set code.";
-
-        final String mangledCode = CodeConverter.tryToDatabase(dataSetCode);
-        final Criterion codeEq = Restrictions.eq("code", mangledCode);
-
-        final DetachedCriteria criteria = DetachedCriteria.forClass(ENTITY_SUPER_CLASS);
-        criteria.add(codeEq);
-        criteria.setFetchMode("dataSetType", FetchMode.JOIN);
-        criteria.setFetchMode("dataStore", FetchMode.JOIN);
-        criteria.setResultTransformer(DetachedCriteria.DISTINCT_ROOT_ENTITY);
-        final List<DataPE> list = cast(getHibernateTemplate().findByCriteria(criteria));
-        final DataPE entity = tryFindEntity(list, "data set");
-
-        if (operationLog.isDebugEnabled())
-        {
-            String methodName = MethodUtils.getCurrentMethod().getName();
-            operationLog.debug(String.format("%s(%s): '%s'.", methodName, dataSetCode, entity));
-        }
-        return entity;
-    }
-
-    public List<ExternalDataPE> tryToFindFullDataSetsByCodes(Collection<String> dataSetCodes,
-            boolean withPropertyTypes, boolean lockForUpdate)
-    {
-        assert dataSetCodes != null : "Unspecified collection";
-
-        if (dataSetCodes.size() == 0)
-        {
-            return Collections.emptyList();
-        }
-
-        final Criterion codeIn = Restrictions.in("code", dataSetCodes);
-
-        final DetachedCriteria criteria = DetachedCriteria.forClass(ENTITY_CLASS);
-        criteria.add(codeIn);
-        criteria.setFetchMode("dataSetType", FetchMode.SELECT);
-        criteria.setFetchMode("dataStore", FetchMode.SELECT);
-        criteria.setFetchMode("experimentInternal", FetchMode.SELECT);
-        criteria.setFetchMode("sampleInternal", FetchMode.SELECT);
-        criteria.setFetchMode("fileFormat", FetchMode.SELECT);
-        if (withPropertyTypes)
-        {
-            criteria.setFetchMode("dataSetType.dataSetTypePropertyTypesInternal", FetchMode.JOIN);
-        }
-        criteria.setResultTransformer(DetachedCriteria.DISTINCT_ROOT_ENTITY);
-        if (lockForUpdate)
-        {
-            criteria.setLockMode(LockMode.UPGRADE);
-        }
-        final List<ExternalDataPE> list = cast(getHibernateTemplate().findByCriteria(criteria));
-
-        if (operationLog.isDebugEnabled())
-        {
-            operationLog.debug(String.format("Found '%s' data sets for codes '%s'.", list.size(),
-                    dataSetCodes));
-        }
-        return list;
-    }
-
-    public ExternalDataPE tryToFindFullDataSetByCode(String dataSetCode, boolean withPropertyTypes,
-            boolean lockForUpdate)
-    {
-        assert dataSetCode != null : "Unspecified data set code";
-
-        final String mangledCode = CodeConverter.tryToDatabase(dataSetCode);
-        final Criterion codeEq = Restrictions.eq("code", mangledCode);
-
-        final DetachedCriteria criteria = DetachedCriteria.forClass(ENTITY_CLASS);
-        criteria.add(codeEq);
-        criteria.setFetchMode("dataSetType", FetchMode.SELECT);
-        criteria.setFetchMode("dataStore", FetchMode.SELECT);
-        criteria.setFetchMode("experimentInternal", FetchMode.SELECT);
-        criteria.setFetchMode("sampleInternal", FetchMode.SELECT);
-        criteria.setFetchMode("fileFormat", FetchMode.SELECT);
-        if (withPropertyTypes)
-        {
-            criteria.setFetchMode("dataSetType.dataSetTypePropertyTypesInternal", FetchMode.JOIN);
-        }
-        criteria.setResultTransformer(DetachedCriteria.DISTINCT_ROOT_ENTITY);
-        if (lockForUpdate)
-        {
-            criteria.setLockMode(LockMode.UPGRADE);
-        }
-        final List<ExternalDataPE> list = cast(getHibernateTemplate().findByCriteria(criteria));
-        final ExternalDataPE entity = tryFindEntity(list, "data set");
-
-        if (operationLog.isDebugEnabled())
-        {
-            operationLog.debug(String.format("External data '%s' found for data set code '%s'.",
-                    entity, dataSetCode));
-        }
-        return entity;
-    }
-
-    public void updateDataSetStatuses(final List<String> dataSetCodes,
-            final DataSetArchivingStatus status)
-    {
-        assert dataSetCodes != null : "Unspecified data set codes";
-        assert status != null : "Unspecified code";
-
-        if (dataSetCodes.size() == 0)
-        {
-            return;
-        }
-
-        final HibernateTemplate hibernateTemplate = getHibernateTemplate();
-        int updatedRows = (Integer) hibernateTemplate.execute(new HibernateCallback()
-            {
-
-                //
-                // HibernateCallback
-                //
-
-                public final Object doInHibernate(final Session session) throws HibernateException,
-                        SQLException
-                {
-                    // NOTE: 'VERSIONED' makes modification time modified too
-                    return session
-                            .createQuery(
-                                    "UPDATE VERSIONED " + TABLE_NAME
-                                            + " SET status = :status WHERE code IN (:codes) ")
-                            .setParameter("status", status).setParameterList("codes", dataSetCodes)
-                            .executeUpdate();
-                }
-            });
-        hibernateTemplate.flush();
-        if (updatedRows != dataSetCodes.size())
-        {
-            throw UserFailureException.fromTemplate("Update of %s data set statuses to %s failed.",
-                    dataSetCodes.size(), status);
-        } else if (operationLog.isInfoEnabled())
-        {
-            operationLog.info(String.format("UPDATED: %s data set statuses to '%s'.",
-                    dataSetCodes.size(), status));
-        }
-    }
-
-    public void updateDataSetStatuses(final List<String> dataSetCodes,
-            final DataSetArchivingStatus status, final boolean presentInArchive)
-    {
-        assert dataSetCodes != null : "Unspecified data set codes";
-        assert status != null : "Unspecified code";
-
-        if (dataSetCodes.size() == 0)
-        {
-            return;
-        }
-
-        final HibernateTemplate hibernateTemplate = getHibernateTemplate();
-        int updatedRows = (Integer) hibernateTemplate.execute(new HibernateCallback()
-            {
-
-                //
-                // HibernateCallback
-                //
-
-                public final Object doInHibernate(final Session session) throws HibernateException,
-                        SQLException
-                {
-                    // NOTE: 'VERSIONED' makes modification time modified too
-                    return session
-                            .createQuery(
-                                    "UPDATE VERSIONED "
-                                            + TABLE_NAME
-                                            + " SET status = :status, presentInArchive = :presentInArchive"
-                                            + " WHERE code IN (:codes) ")
-                            .setParameter("status", status)
-                            .setParameter("presentInArchive", presentInArchive)
-                            .setParameterList("codes", dataSetCodes).executeUpdate();
-                }
-            });
-        hibernateTemplate.flush();
-        if (updatedRows != dataSetCodes.size())
-        {
-            throw UserFailureException.fromTemplate(
-                    "Update of %s data set statuses to '%s' and presentInArchive to '%s' failed.",
-                    dataSetCodes.size(), status, presentInArchive);
-        } else if (operationLog.isInfoEnabled())
-        {
-            operationLog.info(String.format(
-                    "UPDATED: %s data set statuses to '%s' and presentInArchive flag to '%s'.",
-                    dataSetCodes.size(), status, presentInArchive));
-        }
-    }
-
-    public void createDataSet(DataPE dataset)
-    {
-        assert dataset != null : "Unspecified data set.";
-
-        dataset.setCode(CodeConverter.tryToDatabase(dataset.getCode()));
-        final HibernateTemplate template = getHibernateTemplate();
-        if (operationLog.isInfoEnabled())
-        {
-            operationLog.info(String.format("ADD BEFORE SAVE: data set id '%d'.",
-                    HibernateUtils.getId(dataset)));
-        }
-        template.save(dataset);
-        if (operationLog.isInfoEnabled())
-        {
-            operationLog.info(String.format("ADD BEFORE FLUSH: data set id '%d'.",
-                    HibernateUtils.getId(dataset)));
-        }
-
-        template.flush();
-
-        if (dataset instanceof ExternalDataPE)
-        {
-            scheduleDynamicPropertiesEvaluation(Collections.singletonList((ExternalDataPE) dataset));
-        }
-
-        if (operationLog.isInfoEnabled())
-        {
-            operationLog.info(String.format("ADD: data set '%s'.", dataset));
-        }
-    }
-
-    public void updateDataSet(ExternalDataPE externalData)
-    {
-        assert externalData != null : "Given external data can not be null.";
-        validatePE(externalData);
-
-        final HibernateTemplate hibernateTemplate = getHibernateTemplate();
-        externalData.setCode(CodeConverter.tryToDatabase(externalData.getCode()));
-        Long id = HibernateUtils.getId(externalData);
-        final DataPE loaded = (DataPE) hibernateTemplate.load(ENTITY_CLASS, id);
-        // This just means that we do not have any entry in 'EXTERNAL_DATA' table for this id. It
-        // might happen when we work with placeholder data.
-        if (loaded instanceof ExternalDataPE == false)
-        {
-            String shareId = externalData.getShareId();
-            String location = externalData.getLocation();
-            Long size = externalData.getSize();
-            Long locatorTypeID = externalData.getLocatorType().getId();
-            Long fileFormatTypeID = externalData.getFileFormatType().getId();
-            char complete = externalData.getComplete().name().charAt(0);
-            Long storageFormatTermID = externalData.getStorageFormatVocabularyTerm().getId();
-            if (size == null)
-            {
-                executeUpdate(
-                        "insert into "
-                                + TableNames.EXTERNAL_DATA_TABLE
-                                + " (data_id, share_id, location, loty_id, ffty_id, is_complete, cvte_id_stor_fmt) "
-                                + "values (?, ?, ?, ?, ?, ?, ?)", id, shareId, location,
-                        locatorTypeID, fileFormatTypeID, complete, storageFormatTermID);
-            } else
-            {
-                executeUpdate(
-                        "insert into "
-                                + TableNames.EXTERNAL_DATA_TABLE
-                                + " (data_id, share_id, location, size, loty_id, ffty_id, is_complete, cvte_id_stor_fmt) "
-                                + "values (?, ?, ?, ?, ?, ?, ?, ?)", id, shareId, location, size,
-                        locatorTypeID, fileFormatTypeID, complete, storageFormatTermID);
-            }
-            hibernateTemplate.evict(loaded);
-        }
-        hibernateTemplate.update(externalData);
-        hibernateTemplate.flush();
-        scheduleDynamicPropertiesEvaluation(Collections.singletonList(externalData));
-
-        if (operationLog.isInfoEnabled())
-        {
-            operationLog.info(String.format("UPDATE: external data '%s'.", externalData));
-        }
-    }
-
-    @Override
-    public void delete(ExternalDataPE entity) throws DataAccessException
-    {
-        assert entity != null : "entity unspecified";
-        if (entity.getChildren().size() > 0)
-        {
-            throw new DataIntegrityViolationException(
-                    String.format(
-                            "External Data '%s' cannot be deleted because children datasets are connected.",
-                            entity.getCode()));
-        }
-        super.delete(entity);
-    }
-
-    @SuppressWarnings("unchecked")
-    public Set<TechId> findParentIds(final Collection<TechId> dataSetIds)
-    {
-        // Native SQL query is used to be able to query on 'many-to-many association table -
-        // - 'data_set_relationships' without join with 'data' table involved in this association.
-        // Drawback of this solution is that instead of list of Long values we get list of
-        // BigIntegers and so a transformation is needed.
-
-        final String query =
-                "select data_id_parent from data_set_relationships where data_id_child in (:ids)";
-        final List<? extends Number> results =
-                (List<? extends Number>) getHibernateTemplate().execute(new HibernateCallback()
-                    {
-
-                        //
-                        // HibernateCallback
-                        //
-
-                        public final Object doInHibernate(final Session session)
-                        {
-                            // we could remove this transformation if we choose to pass Long values
-                            final List<Long> longIds = TechId.asLongs(dataSetIds);
-                            return session.createSQLQuery(query).setParameterList("ids", longIds)
-                                    .list();
-                        }
-                    });
-        return transformNumbers2TechIdSet(results);
-    }
-
-    // data set relationship helper methods
-
-    public List<ExternalDataPE> listByCode(Set<String> values)
-    {
-        if (values == null || values.isEmpty())
-        {
-            return new ArrayList<ExternalDataPE>();
-        }
-        final DetachedCriteria criteria = DetachedCriteria.forClass(ExternalDataPE.class);
-        criteria.add(Restrictions.in("code", values));
-        final List<ExternalDataPE> list = cast(getHibernateTemplate().findByCriteria(criteria));
-        if (operationLog.isDebugEnabled())
-        {
-            operationLog.debug(String.format("%d data set(s) have been found.", list.size()));
-        }
-        return list;
-    }
-
-    public void updateDataSets(List<ExternalDataPE> externalData)
-    {
-        assert externalData != null : "Data sets not defined";
-
-        final HibernateTemplate hibernateTemplate = getHibernateTemplate();
-        for (ExternalDataPE ed : externalData)
-        {
-            validatePE(ed);
-            ed.setCode(CodeConverter.tryToDatabase(ed.getCode()));
-            hibernateTemplate.saveOrUpdate(ed);
-        }
-
-        if (operationLog.isInfoEnabled())
-        {
-            operationLog.info(String.format("UPDATE: %d data sets.", externalData.size()));
-        }
-
-        flushWithSqlExceptionHandling(getHibernateTemplate());
-        scheduleDynamicPropertiesEvaluation(externalData);
-
-        // if session is not cleared registration of many samples slows down after each batch
-        hibernateTemplate.clear();
-    }
-
-    @Override
-    public final void validateAndSaveUpdatedEntity(ExternalDataPE entity)
-            throws DataAccessException
-    {
-        super.validateAndSaveUpdatedEntity(entity);
-        scheduleDynamicPropertiesEvaluation(Arrays.asList(entity));
-    }
-
-    @Override
-    Logger getLogger()
-    {
-        return operationLog;
-    }
-
-}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java
index 064ab4c86b7..90260a91c69 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java
@@ -743,4 +743,12 @@ public interface IETLLIMSService extends IServer, ISessionProvider
     @RolesAllowed(RoleWithHierarchy.SPACE_ETL_SERVER)
     public List<String> getTrustedCrossOriginDomains(String sessionToken);
 
+    /**
+     * Marks the storage of dataset as confirmed.
+     */
+    @Transactional
+    @RolesAllowed(RoleWithHierarchy.SPACE_ETL_SERVER)
+    @DatabaseUpdateModification(value =
+        { ObjectKind.DATA_SET })
+    public void setStorageConfirmed(String sessionToken, String dataSetCode);
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExternalDataPE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExternalDataPE.java
index 9b21f342c16..8f8279f6d72 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExternalDataPE.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExternalDataPE.java
@@ -83,7 +83,7 @@ public final class ExternalDataPE extends DataPE
     // TODO: Storage confirmation should be set to false.
     // At the moment however the logic is not yet implemented, and we want all objects in database
     // to have true initialy.
-    private boolean storageConfirmation = true;
+    private boolean storageConfirmation = false;
 
     private int speedHint = Constants.DEFAULT_SPEED_HINT;
 
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceTest.java
index ed009330ba9..7105227aea7 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceTest.java
@@ -1139,6 +1139,13 @@ public class ETLServiceTest extends AbstractServerTestCase
         context.assertIsSatisfied();
     }
 
+    public void testDataSetCofirmation()
+    {
+        // TODO:kuba
+        // call etlservice method setStorageConfirmed
+        // make sure the method setstorageConfirmed was claled on the databo object
+    }
+
     private SearchCriteria createSearchCriteriaForSample()
     {
         SearchCriteria sc = new SearchCriteria();
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataBOTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataBOTest.java
index ec508efd4ec..3093d0e7d38 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataBOTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataBOTest.java
@@ -935,6 +935,18 @@ public class DataBOTest extends AbstractBOTest
         context.assertIsSatisfied();
     }
 
+    public void testStorageConfirmed()
+    {
+        // TODO:KUBA
+        // create a new data object with external data.
+        // check that externaldataPE has isstorage confirmed set to false
+
+        // call dataBo. setstorageconfirmed on this instance of external data
+
+        // check that the isstorage confirmed is now true on this element
+
+    }
+
     @SuppressWarnings("unchecked")
     private void expectMandatoryPropertiesCheck(Expectations exp, final DataSetTypePE type)
     {
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java.expected b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java.expected
index 064ab4c86b7..90260a91c69 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java.expected
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java.expected
@@ -743,4 +743,12 @@ public interface IETLLIMSService extends IServer, ISessionProvider
     @RolesAllowed(RoleWithHierarchy.SPACE_ETL_SERVER)
     public List<String> getTrustedCrossOriginDomains(String sessionToken);
 
+    /**
+     * Marks the storage of dataset as confirmed.
+     */
+    @Transactional
+    @RolesAllowed(RoleWithHierarchy.SPACE_ETL_SERVER)
+    @DatabaseUpdateModification(value =
+        { ObjectKind.DATA_SET })
+    public void setStorageConfirmed(String sessionToken, String dataSetCode);
 }
-- 
GitLab