Skip to content
Snippets Groups Projects
Commit 2c90904c authored by pkupczyk's avatar pkupczyk
Browse files

SSDM-2706 : V3 AS API - create data sets (only metadata) - check that...

SSDM-2706 : V3 AS API - create data sets (only metadata) - check that container is actually of container type (also during data set update)

SVN: 34997
parent d21957c0
No related branches found
No related tags found
No related merge requests found
Showing
with 78 additions and 47 deletions
...@@ -50,7 +50,7 @@ public class UpdateDataSetChildrenExecutor extends AbstractUpdateEntityToManyRel ...@@ -50,7 +50,7 @@ public class UpdateDataSetChildrenExecutor extends AbstractUpdateEntityToManyRel
} }
@Override @Override
protected void check(IOperationContext context, IDataSetId relatedId, DataPE related) protected void check(IOperationContext context, DataPE entity, IDataSetId relatedId, DataPE related)
{ {
if (false == new DataSetPEByExperimentOrSampleIdentifierValidator().doValidation(context.getSession().tryGetPerson(), related)) if (false == new DataSetPEByExperimentOrSampleIdentifierValidator().doValidation(context.getSession().tryGetPerson(), related))
{ {
......
...@@ -26,6 +26,7 @@ import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.IdListUpdateValue; ...@@ -26,6 +26,7 @@ import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.IdListUpdateValue;
import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.dataset.DataSetUpdate; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.dataset.DataSetUpdate;
import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.dataset.IDataSetId; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.dataset.IDataSetId;
import ch.ethz.sis.openbis.generic.shared.api.v3.exceptions.UnauthorizedObjectAccessException; import ch.ethz.sis.openbis.generic.shared.api.v3.exceptions.UnauthorizedObjectAccessException;
import ch.systemsx.cisd.common.exceptions.UserFailureException;
import ch.systemsx.cisd.openbis.generic.server.authorization.validator.DataSetPEByExperimentOrSampleIdentifierValidator; import ch.systemsx.cisd.openbis.generic.server.authorization.validator.DataSetPEByExperimentOrSampleIdentifierValidator;
import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE; import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE;
...@@ -50,12 +51,17 @@ public class UpdateDataSetContainedExecutor extends AbstractUpdateEntityToManyRe ...@@ -50,12 +51,17 @@ public class UpdateDataSetContainedExecutor extends AbstractUpdateEntityToManyRe
} }
@Override @Override
protected void check(IOperationContext context, IDataSetId relatedId, DataPE related) protected void check(IOperationContext context, DataPE entity, IDataSetId relatedId, DataPE related)
{ {
if (false == new DataSetPEByExperimentOrSampleIdentifierValidator().doValidation(context.getSession().tryGetPerson(), related)) if (false == new DataSetPEByExperimentOrSampleIdentifierValidator().doValidation(context.getSession().tryGetPerson(), related))
{ {
throw new UnauthorizedObjectAccessException(relatedId); throw new UnauthorizedObjectAccessException(relatedId);
} }
if (false == entity.isContainer())
{
throw new UserFailureException("Data set " + entity.getCode()
+ " is not of a container type therefore cannot have contained data sets.");
}
} }
@Override @Override
......
...@@ -26,6 +26,7 @@ import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.IdListUpdateValue; ...@@ -26,6 +26,7 @@ import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.IdListUpdateValue;
import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.dataset.DataSetUpdate; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.dataset.DataSetUpdate;
import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.dataset.IDataSetId; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.dataset.IDataSetId;
import ch.ethz.sis.openbis.generic.shared.api.v3.exceptions.UnauthorizedObjectAccessException; import ch.ethz.sis.openbis.generic.shared.api.v3.exceptions.UnauthorizedObjectAccessException;
import ch.systemsx.cisd.common.exceptions.UserFailureException;
import ch.systemsx.cisd.openbis.generic.server.authorization.validator.DataSetPEByExperimentOrSampleIdentifierValidator; import ch.systemsx.cisd.openbis.generic.server.authorization.validator.DataSetPEByExperimentOrSampleIdentifierValidator;
import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE; import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE;
...@@ -50,7 +51,7 @@ public class UpdateDataSetContainersExecutor extends AbstractUpdateEntityToManyR ...@@ -50,7 +51,7 @@ public class UpdateDataSetContainersExecutor extends AbstractUpdateEntityToManyR
} }
@Override @Override
protected void check(IOperationContext context, IDataSetId relatedId, DataPE related) protected void check(IOperationContext context, DataPE entity, IDataSetId relatedId, DataPE related)
{ {
if (false == new DataSetPEByExperimentOrSampleIdentifierValidator().doValidation(context.getSession().tryGetPerson(), related)) if (false == new DataSetPEByExperimentOrSampleIdentifierValidator().doValidation(context.getSession().tryGetPerson(), related))
{ {
...@@ -61,6 +62,11 @@ public class UpdateDataSetContainersExecutor extends AbstractUpdateEntityToManyR ...@@ -61,6 +62,11 @@ public class UpdateDataSetContainersExecutor extends AbstractUpdateEntityToManyR
@Override @Override
protected void add(IOperationContext context, DataPE entity, DataPE related) protected void add(IOperationContext context, DataPE entity, DataPE related)
{ {
if (false == related.isContainer())
{
throw new UserFailureException("Data set " + related.getCode()
+ " is not of a container type therefore cannot be set as a container of data set " + entity.getCode() + ".");
}
relationshipService.assignDataSetToContainer(context.getSession(), entity, related); relationshipService.assignDataSetToContainer(context.getSession(), entity, related);
} }
......
...@@ -50,7 +50,7 @@ public class UpdateDataSetParentsExecutor extends AbstractUpdateEntityToManyRela ...@@ -50,7 +50,7 @@ public class UpdateDataSetParentsExecutor extends AbstractUpdateEntityToManyRela
} }
@Override @Override
protected void check(IOperationContext context, IDataSetId relatedId, DataPE related) protected void check(IOperationContext context, DataPE entity, IDataSetId relatedId, DataPE related)
{ {
if (false == new DataSetPEByExperimentOrSampleIdentifierValidator().doValidation(context.getSession().tryGetPerson(), related)) if (false == new DataSetPEByExperimentOrSampleIdentifierValidator().doValidation(context.getSession().tryGetPerson(), related))
{ {
......
...@@ -69,7 +69,7 @@ public abstract class AbstractUpdateEntityToManyRelationExecutor<ENTITY_UPDATE, ...@@ -69,7 +69,7 @@ public abstract class AbstractUpdateEntityToManyRelationExecutor<ENTITY_UPDATE,
{ {
throw new ObjectNotFoundException((IObjectId) relatedId); throw new ObjectNotFoundException((IObjectId) relatedId);
} }
check(context, relatedId, related); check(context, entity, relatedId, related);
relatedCollection.add(related); relatedCollection.add(related);
} }
if (action instanceof ListUpdateActionSet<?>) if (action instanceof ListUpdateActionSet<?>)
...@@ -88,7 +88,7 @@ public abstract class AbstractUpdateEntityToManyRelationExecutor<ENTITY_UPDATE, ...@@ -88,7 +88,7 @@ public abstract class AbstractUpdateEntityToManyRelationExecutor<ENTITY_UPDATE,
{ {
relatedCollection.add(related); relatedCollection.add(related);
} }
check(context, relatedId, related); check(context, entity, relatedId, related);
} }
remove(context, entity, relatedCollection); remove(context, entity, relatedCollection);
} }
...@@ -150,7 +150,7 @@ public abstract class AbstractUpdateEntityToManyRelationExecutor<ENTITY_UPDATE, ...@@ -150,7 +150,7 @@ public abstract class AbstractUpdateEntityToManyRelationExecutor<ENTITY_UPDATE,
protected abstract IdListUpdateValue<? extends RELATED_ID> getRelatedUpdate(IOperationContext context, ENTITY_UPDATE update); protected abstract IdListUpdateValue<? extends RELATED_ID> getRelatedUpdate(IOperationContext context, ENTITY_UPDATE update);
protected abstract void check(IOperationContext context, RELATED_ID relatedId, RELATED_PE related); protected abstract void check(IOperationContext context, ENTITY_PE entity, RELATED_ID relatedId, RELATED_PE related);
protected abstract void add(IOperationContext context, ENTITY_PE entity, RELATED_PE related); protected abstract void add(IOperationContext context, ENTITY_PE entity, RELATED_PE related);
......
...@@ -50,7 +50,7 @@ public class UpdateSampleChildrenExecutor extends AbstractUpdateEntityToManyRela ...@@ -50,7 +50,7 @@ public class UpdateSampleChildrenExecutor extends AbstractUpdateEntityToManyRela
} }
@Override @Override
protected void check(IOperationContext context, ISampleId relatedId, SamplePE related) protected void check(IOperationContext context, SamplePE entity, ISampleId relatedId, SamplePE related)
{ {
if (false == new SampleByIdentiferValidator().doValidation(context.getSession().tryGetPerson(), related)) if (false == new SampleByIdentiferValidator().doValidation(context.getSession().tryGetPerson(), related))
{ {
......
...@@ -54,7 +54,7 @@ public class UpdateSampleContainedExecutor extends AbstractUpdateEntityToManyRel ...@@ -54,7 +54,7 @@ public class UpdateSampleContainedExecutor extends AbstractUpdateEntityToManyRel
} }
@Override @Override
protected void check(IOperationContext context, ISampleId relatedId, SamplePE related) protected void check(IOperationContext context, SamplePE entity, ISampleId relatedId, SamplePE related)
{ {
if (false == new SampleByIdentiferValidator().doValidation(context.getSession().tryGetPerson(), related)) if (false == new SampleByIdentiferValidator().doValidation(context.getSession().tryGetPerson(), related))
{ {
......
...@@ -50,7 +50,7 @@ public class UpdateSampleParentsExecutor extends AbstractUpdateEntityToManyRelat ...@@ -50,7 +50,7 @@ public class UpdateSampleParentsExecutor extends AbstractUpdateEntityToManyRelat
} }
@Override @Override
protected void check(IOperationContext context, ISampleId relatedId, SamplePE related) protected void check(IOperationContext context, SamplePE entity, ISampleId relatedId, SamplePE related)
{ {
if (false == new SampleByIdentiferValidator().doValidation(context.getSession().tryGetPerson(), related)) if (false == new SampleByIdentiferValidator().doValidation(context.getSession().tryGetPerson(), related))
{ {
......
...@@ -27,9 +27,6 @@ import java.util.Map; ...@@ -27,9 +27,6 @@ import java.util.Map;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.ListUpdateValue.ListUpdateAction;
import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.ListUpdateValue.ListUpdateActionAdd;
import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.ListUpdateValue.ListUpdateActionRemove;
import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.dataset.DataSet; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.dataset.DataSet;
import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.dataset.DataSetUpdate; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.dataset.DataSetUpdate;
import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.dataset.PhysicalDataUpdate; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.dataset.PhysicalDataUpdate;
...@@ -42,7 +39,6 @@ import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.experiment.ExperimentIde ...@@ -42,7 +39,6 @@ import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.experiment.ExperimentIde
import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.experiment.ExperimentPermId; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.experiment.ExperimentPermId;
import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.experiment.IExperimentId; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.experiment.IExperimentId;
import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.sample.SamplePermId; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.sample.SamplePermId;
import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.tag.ITagId;
import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.tag.TagCode; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.tag.TagCode;
import ch.systemsx.cisd.common.action.IDelegatedAction; import ch.systemsx.cisd.common.action.IDelegatedAction;
import ch.systemsx.cisd.common.exceptions.UserFailureException; import ch.systemsx.cisd.common.exceptions.UserFailureException;
...@@ -399,10 +395,7 @@ public class UpdateDataSetTest extends AbstractSampleTest ...@@ -399,10 +395,7 @@ public class UpdateDataSetTest extends AbstractSampleTest
DataSetUpdate update = new DataSetUpdate(); DataSetUpdate update = new DataSetUpdate();
update.setDataSetId(dataSetId); update.setDataSetId(dataSetId);
ListUpdateAction<IDataSetId> addAction = new ListUpdateActionAdd<IDataSetId>(); update.getParentIds().add(new DataSetPermId("20081105092259000-20"));
addAction.setItems(Collections.singletonList(new DataSetPermId("20081105092259000-20")));
update.setParentActions(Collections.singletonList(addAction));
v3api.updateDataSets(sessionToken, Collections.singletonList(update)); v3api.updateDataSets(sessionToken, Collections.singletonList(update));
...@@ -423,9 +416,7 @@ public class UpdateDataSetTest extends AbstractSampleTest ...@@ -423,9 +416,7 @@ public class UpdateDataSetTest extends AbstractSampleTest
DataSetUpdate update = new DataSetUpdate(); DataSetUpdate update = new DataSetUpdate();
update.setDataSetId(originalChild); update.setDataSetId(originalChild);
ListUpdateAction<IDataSetId> removeAction = new ListUpdateActionRemove<IDataSetId>(); update.getParentIds().remove(originalParent);
removeAction.setItems(Collections.singletonList(originalParent));
update.setParentActions(Collections.singletonList(removeAction));
assertRemovingParent(originalChild, originalParent, update); assertRemovingParent(originalChild, originalParent, update);
} }
...@@ -460,9 +451,7 @@ public class UpdateDataSetTest extends AbstractSampleTest ...@@ -460,9 +451,7 @@ public class UpdateDataSetTest extends AbstractSampleTest
DataSetUpdate update = new DataSetUpdate(); DataSetUpdate update = new DataSetUpdate();
update.setDataSetId(originalParent); update.setDataSetId(originalParent);
ListUpdateAction<IDataSetId> removeAction = new ListUpdateActionRemove<IDataSetId>(); update.getChildIds().remove(originalChild);
removeAction.setItems(Collections.singletonList(originalChild));
update.setChildActions(Collections.singletonList(removeAction));
assertRemovingParent(originalChild, originalParent, update); assertRemovingParent(originalChild, originalParent, update);
} }
...@@ -494,8 +483,8 @@ public class UpdateDataSetTest extends AbstractSampleTest ...@@ -494,8 +483,8 @@ public class UpdateDataSetTest extends AbstractSampleTest
{ {
final String sessionToken = v3api.login(TEST_USER, PASSWORD); final String sessionToken = v3api.login(TEST_USER, PASSWORD);
DataSetPermId dataSetId = new DataSetPermId("20081105092259000-8"); DataSetPermId dataSetId = new DataSetPermId("CONTAINER_1");
final DataSetPermId componentId = new DataSetPermId("20081105092259000-9"); final DataSetPermId componentId = new DataSetPermId("CONTAINER_2");
final DataSetUpdate update = new DataSetUpdate(); final DataSetUpdate update = new DataSetUpdate();
update.setDataSetId(dataSetId); update.setDataSetId(dataSetId);
...@@ -509,7 +498,7 @@ public class UpdateDataSetTest extends AbstractSampleTest ...@@ -509,7 +498,7 @@ public class UpdateDataSetTest extends AbstractSampleTest
{ {
v3api.updateDataSets(sessionToken, Collections.singletonList(update)); v3api.updateDataSets(sessionToken, Collections.singletonList(update));
} }
}, "Circular dependency found: 20081105092259000-8"); }, "Circular dependency found: CONTAINER_1");
} }
@Test @Test
...@@ -521,12 +510,8 @@ public class UpdateDataSetTest extends AbstractSampleTest ...@@ -521,12 +510,8 @@ public class UpdateDataSetTest extends AbstractSampleTest
DataSetUpdate update = new DataSetUpdate(); DataSetUpdate update = new DataSetUpdate();
update.setDataSetId(dataSetId); update.setDataSetId(dataSetId);
ListUpdateActionAdd<IDataSetId> addAction = new ListUpdateActionAdd<IDataSetId>(); update.getContainedIds().add(new DataSetPermId("COMPONENT_2A"));
ListUpdateAction<IDataSetId> removeAction = new ListUpdateActionRemove<IDataSetId>(); update.getContainedIds().remove(new DataSetPermId("COMPONENT_1A"));
addAction.setItems(Collections.singletonList(new DataSetPermId("COMPONENT_2A")));
removeAction.setItems(Collections.singletonList(new DataSetPermId("COMPONENT_1A")));
update.setContainedActions(Arrays.asList(addAction, removeAction));
v3api.updateDataSets(sessionToken, Collections.singletonList(update)); v3api.updateDataSets(sessionToken, Collections.singletonList(update));
...@@ -537,6 +522,25 @@ public class UpdateDataSetTest extends AbstractSampleTest ...@@ -537,6 +522,25 @@ public class UpdateDataSetTest extends AbstractSampleTest
AssertionUtil.assertCollectionContainsOnly(dataSetCodes(result.getContained()), "COMPONENT_1B", "COMPONENT_2A"); AssertionUtil.assertCollectionContainsOnly(dataSetCodes(result.getContained()), "COMPONENT_1B", "COMPONENT_2A");
} }
@Test
public void testUpdateWithComponentWithNonContainerDataSet()
{
final String sessionToken = v3api.login(TEST_USER, PASSWORD);
final DataSetUpdate update = new DataSetUpdate();
update.setDataSetId(new DataSetPermId("COMPONENT_1A"));
update.getContainedIds().add(new DataSetPermId("COMPONENT_2A"));
assertUserFailureException(new IDelegatedAction()
{
@Override
public void execute()
{
v3api.updateDataSets(sessionToken, Collections.singletonList(update));
}
}, "Data set COMPONENT_1A is not of a container type therefore cannot have contained data sets.");
}
@Test @Test
public void testUpdateWithContainerAddRemove() public void testUpdateWithContainerAddRemove()
{ {
...@@ -550,12 +554,8 @@ public class UpdateDataSetTest extends AbstractSampleTest ...@@ -550,12 +554,8 @@ public class UpdateDataSetTest extends AbstractSampleTest
DataSetUpdate update = new DataSetUpdate(); DataSetUpdate update = new DataSetUpdate();
update.setDataSetId(dataSetId); update.setDataSetId(dataSetId);
ListUpdateActionAdd<IDataSetId> addAction = new ListUpdateActionAdd<IDataSetId>(); update.getContainerIds().add(cont2, cont3a);
ListUpdateAction<IDataSetId> removeAction = new ListUpdateActionRemove<IDataSetId>(); update.getContainerIds().remove(cont1);
addAction.setItems(Arrays.asList(cont2, cont3a));
removeAction.setItems(Collections.singletonList(cont1));
update.setContainerActions(Arrays.asList(addAction, removeAction));
v3api.updateDataSets(sessionToken, Collections.singletonList(update)); v3api.updateDataSets(sessionToken, Collections.singletonList(update));
...@@ -572,6 +572,28 @@ public class UpdateDataSetTest extends AbstractSampleTest ...@@ -572,6 +572,28 @@ public class UpdateDataSetTest extends AbstractSampleTest
AssertionUtil.assertCollectionContains(dataSetCodes(map.get(cont3a).getContained()), dataSetId.getPermId()); AssertionUtil.assertCollectionContains(dataSetCodes(map.get(cont3a).getContained()), dataSetId.getPermId());
} }
@Test
public void testUpdateWithContainerAddNotContainerDataSet()
{
final String sessionToken = v3api.login(TEST_USER, PASSWORD);
DataSetPermId dataSetId = new DataSetPermId("CONTAINER_1");
DataSetPermId containerId = new DataSetPermId("COMPONENT_2A");
final DataSetUpdate update = new DataSetUpdate();
update.setDataSetId(dataSetId);
update.getContainerIds().add(containerId);
assertUserFailureException(new IDelegatedAction()
{
@Override
public void execute()
{
v3api.updateDataSets(sessionToken, Collections.singletonList(update));
}
}, "Data set COMPONENT_2A is not of a container type therefore cannot be set as a container of data set CONTAINER_1.");
}
@Test @Test
public void testUpdateWithContainerUnauthorized() public void testUpdateWithContainerUnauthorized()
{ {
...@@ -610,9 +632,8 @@ public class UpdateDataSetTest extends AbstractSampleTest ...@@ -610,9 +632,8 @@ public class UpdateDataSetTest extends AbstractSampleTest
// add tag1 // add tag1
DataSetUpdate firstUpdate = new DataSetUpdate(); DataSetUpdate firstUpdate = new DataSetUpdate();
firstUpdate.setDataSetId(dataSet); firstUpdate.setDataSetId(dataSet);
ListUpdateAction<ITagId> addAction = new ListUpdateActionAdd<ITagId>(); firstUpdate.getTagIds().add(newTag1);
addAction.setItems(Arrays.asList(newTag1));
firstUpdate.setTagActions(Arrays.asList(addAction));
v3api.updateDataSets(sessionToken, Arrays.asList(firstUpdate)); v3api.updateDataSets(sessionToken, Arrays.asList(firstUpdate));
Map<IDataSetId, DataSet> result = v3api.mapDataSets(sessionToken, Arrays.asList(dataSet), fe); Map<IDataSetId, DataSet> result = v3api.mapDataSets(sessionToken, Arrays.asList(dataSet), fe);
...@@ -621,11 +642,9 @@ public class UpdateDataSetTest extends AbstractSampleTest ...@@ -621,11 +642,9 @@ public class UpdateDataSetTest extends AbstractSampleTest
// remove test_metaprojects and add a new tag2 // remove test_metaprojects and add a new tag2
DataSetUpdate secondUpdate = new DataSetUpdate(); DataSetUpdate secondUpdate = new DataSetUpdate();
secondUpdate.setDataSetId(dataSet); secondUpdate.setDataSetId(dataSet);
addAction = new ListUpdateActionAdd<ITagId>(); secondUpdate.getTagIds().remove(existingTag);
ListUpdateAction<ITagId> removeAction = new ListUpdateActionRemove<ITagId>(); secondUpdate.getTagIds().add(newTag2);
addAction.setItems(Arrays.asList(newTag2));
removeAction.setItems(Arrays.asList(existingTag));
secondUpdate.setTagActions(Arrays.asList(addAction, removeAction));
v3api.updateDataSets(sessionToken, Arrays.asList(secondUpdate)); v3api.updateDataSets(sessionToken, Arrays.asList(secondUpdate));
result = v3api.mapDataSets(sessionToken, Arrays.asList(dataSet), fe); result = v3api.mapDataSets(sessionToken, Arrays.asList(dataSet), fe);
......
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