Skip to content
Snippets Groups Projects
Commit a890b589 authored by kaloyane's avatar kaloyane
Browse files

[LMS-2282] implement full DFS validation for container-component relationship

SVN: 21639
parent c58bb1be
No related branches found
No related tags found
No related merge requests found
...@@ -32,6 +32,7 @@ import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory; ...@@ -32,6 +32,7 @@ import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDataDAO; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDataDAO;
import ch.systemsx.cisd.openbis.generic.server.dataaccess.IVocabularyDAO; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IVocabularyDAO;
import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; 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.DataSetArchivingStatus; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetArchivingStatus;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetType; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetType;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityProperty;
...@@ -572,19 +573,33 @@ public class DataBO extends AbstractDataSetBusinessObject implements IDataBO ...@@ -572,19 +573,33 @@ public class DataBO extends AbstractDataSetBusinessObject implements IDataBO
// quick check for direct cycle // quick check for direct cycle
final Set<String> brandNewCodes = new HashSet<String>(newCodes); final Set<String> brandNewCodes = new HashSet<String>(newCodes);
brandNewCodes.removeAll(currentCodes); brandNewCodes.removeAll(currentCodes);
if (brandNewCodes.contains(data.getCode()))
{
throw new UserFailureException("Data set '" + data.getCode()
+ "' can not be its own component.");
}
// TODO 2011-05-16, Piotr Buczek: validation of container relationship graph
// validateContainerRelationshipGraph(componentsToAdd);
validateContainerRelationshipGraph(brandNewCodes);
final List<DataPE> newComponents = findDataSetsByCodes(newCodes); final List<DataPE> newComponents = findDataSetsByCodes(newCodes);
addComponents(newComponents); addComponents(newComponents);
} }
} }
private void validateContainerRelationshipGraph(Collection<String> componentCodes)
{
if (componentCodes.contains(data.getCode()))
{
throw new UserFailureException("Data set '" + data.getCode()
+ "' cannot contain itself as a component neither directly nor via subordinate components.");
}
final List<DataPE> components = findDataSetsByCodes(componentCodes);
for (DataPE componentDataSet : components)
{
if (componentDataSet.isContainer())
{
List<DataPE> containedDataSets = componentDataSet.getContainedDataSets();
validateContainerRelationshipGraph(Code.extractCodes(containedDataSets));
}
}
}
/** /**
* Throws {@link UserFailureException} if adding specified parents to this data set will create * Throws {@link UserFailureException} if adding specified parents to this data set will create
* a cycle in data set relationships. * a cycle in data set relationships.
...@@ -685,7 +700,7 @@ public class DataBO extends AbstractDataSetBusinessObject implements IDataBO ...@@ -685,7 +700,7 @@ public class DataBO extends AbstractDataSetBusinessObject implements IDataBO
} }
} }
private List<DataPE> findDataSetsByCodes(Set<String> codes) private List<DataPE> findDataSetsByCodes(Collection<String> codes)
{ {
final IDataDAO dao = getDataDAO(); final IDataDAO dao = getDataDAO();
final List<DataPE> dataSets = new ArrayList<DataPE>(); final List<DataPE> dataSets = new ArrayList<DataPE>();
......
...@@ -690,12 +690,53 @@ public class DataBOTest extends AbstractBOTest ...@@ -690,12 +690,53 @@ public class DataBOTest extends AbstractBOTest
fail("UserFailureException expected"); fail("UserFailureException expected");
} catch (UserFailureException e) } catch (UserFailureException e)
{ {
assertEquals("Data set 'DS1' can not be its own component.", e.getMessage()); assertEquals("Data set 'DS1' cannot contain itself as a "
+ "component neither directly nor via subordinate components.", e.getMessage());
} }
context.assertIsSatisfied(); context.assertIsSatisfied();
} }
@Test
public void testUpdateWithContainerRecursivelyContainingItself()
{
final ExperimentPE experiment =
createExperiment(EXPERIMENT_IDENTIFIER.getExperimentCode(), "spaceCode");
final DataPE container1 = createDataSet("container-1", null, experiment);
container1.getDataSetType().setContainerType(true);
final DataPE container2 = createDataSet("container-2", null, experiment);
container2.getDataSetType().setContainerType(true);
container2.addComponent(container1);
DataSetUpdatesDTO dataSetUpdatesDTO =
createDataSetUpdates(container1, null, EXPERIMENT_IDENTIFIER);
String[] componentCodes =
{ container2.getCode() };
dataSetUpdatesDTO.setModifiedContainedDatasetCodesOrNull(componentCodes);
prepareForUpdate(container1, experiment);
context.checking(new Expectations()
{
{
one(dataDAO).tryToFindDataSetByCode(container2.getCode());
will(returnValue(container2));
}
});
IDataBO dataBO = createDataBO();
try
{
dataBO.update(dataSetUpdatesDTO);
fail("UserFailureException expected");
} catch (UserFailureException e)
{
assertEquals("Data set 'container-1' cannot contain itself as a component"
+ " neither directly nor via subordinate components.", e.getMessage());
}
context.assertIsSatisfied();
}
private void prepareForUpdate(final ExternalDataPE dataSet, final SamplePE sample) private void prepareForUpdate(final ExternalDataPE dataSet, final SamplePE sample)
{ {
context.checking(new Expectations() context.checking(new Expectations()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment