diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java index 20db614b3cd84f8ef0051d06429793b8aa27ecf7..1f3be2df8d235b043edef01d1f35ed824366fd5e 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java @@ -1576,7 +1576,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt columns.add(NewSample.IDENTIFIER_COLUMN); } columns.add(NewSample.CONTAINER); - columns.add(NewSample.PARENT); + columns.add(NewSample.PARENTS); if (withExperiments) columns.add(NewSample.EXPERIMENT); addProperties(columns, ((SampleTypePE) entityType).getSampleTypePropertyTypes()); 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 0fa57e1cb497d584126a93a1927032e53c872e6c..bd31cad1aa7c6e9c70ef8b759b40ad8832ddba20 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 @@ -206,7 +206,7 @@ abstract class AbstractSampleBusinessObject extends AbstractSampleIdentifierBusi final SamplePE samplePE, String parentIdentifier) { final Set<SamplePE> newParents = new HashSet<SamplePE>(); - final SamplePE parentOrNull = tryGetValidSample(parentIdentifier, sampleIdentifier); + final SamplePE parentOrNull = tryGetValidParentSample(parentIdentifier, sampleIdentifier); if (parentOrNull != null) { newParents.add(parentOrNull); @@ -230,6 +230,7 @@ abstract class AbstractSampleBusinessObject extends AbstractSampleIdentifierBusi final Set<SamplePE> parentPEs = new HashSet<SamplePE>(); for (SampleIdentifier si : parentIdentifiers) { + // TODO 2010-11-10, Piotr Buczek: use cache SamplePE parent = getSampleByIdentifier(si); parentPEs.add(parent); } @@ -238,6 +239,10 @@ abstract class AbstractSampleBusinessObject extends AbstractSampleIdentifierBusi private void replaceParents(SamplePE child, Set<SamplePE> newParents) { + for (SamplePE parent : newParents) + { + checkParentInvalidation(parent, child.getSampleIdentifier()); + } List<SampleRelationshipPE> oldParents = new ArrayList<SampleRelationshipPE>(); for (SampleRelationshipPE r : child.getParentRelationships()) { @@ -280,8 +285,8 @@ abstract class AbstractSampleBusinessObject extends AbstractSampleIdentifierBusi return result; } - private SamplePE tryGetValidSample(final String parentIdentifierOrNull, - final SampleIdentifier sampleIdentifier) + private SamplePE tryGetValidParentSample(final String parentIdentifierOrNull, + final SampleIdentifier childIdentifier) { if (parentIdentifierOrNull == null) { @@ -289,19 +294,24 @@ abstract class AbstractSampleBusinessObject extends AbstractSampleIdentifierBusi } final SamplePE parentPE = getSampleByIdentifier(SampleIdentifierFactory.parse(parentIdentifierOrNull)); + checkParentInvalidation(parentPE, childIdentifier); + return parentPE; + } + + private void checkParentInvalidation(final SamplePE parentPE, final SampleIdentifier child) + { if (parentPE.getInvalidation() != null) { throw UserFailureException.fromTemplate( - "Cannot register sample '%s': parent '%s' has been invalidated.", - sampleIdentifier, parentIdentifierOrNull); + "Sample '%s' has been invalidated and can't become a parent of sample '%s'.", + parentPE.getIdentifier(), child); } - return parentPE; } private SamplePE tryGetValidNotContainedSample(final String parentIdentifierOrNull, final SampleIdentifier sampleIdentifier) { - SamplePE sample = tryGetValidSample(parentIdentifierOrNull, sampleIdentifier); + SamplePE sample = tryGetValidParentSample(parentIdentifierOrNull, sampleIdentifier); if (sample != null && sample.getContainer() != null) { throw UserFailureException.fromTemplate( diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractSampleIdentifierBusinessObject.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractSampleIdentifierBusinessObject.java index 767854451664157a48de29c90bc4183e8e07c281..b504e0c0ffba7fbc15a414dca287bf4b24008f2f 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractSampleIdentifierBusinessObject.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractSampleIdentifierBusinessObject.java @@ -70,6 +70,7 @@ abstract class AbstractSampleIdentifierBusinessObject extends AbstractBusinessOb protected SamplePE tryToGetSampleByIdentifier(final SampleIdentifier sampleIdentifier) { + // TODO 2010-11-10, Piotr Buczek: use cache assert sampleIdentifier != null : "Sample identifier unspecified."; final SampleOwner sampleOwner = sampleOwnerFinder.figureSampleOwner(sampleIdentifier); final String sampleCode = sampleIdentifier.getSampleCode(); @@ -78,8 +79,8 @@ abstract class AbstractSampleIdentifierBusinessObject extends AbstractBusinessOb if (sampleOwner.isDatabaseInstanceLevel()) { sample = - sampleDAO.tryFindByCodeAndDatabaseInstance(sampleCode, sampleOwner - .tryGetDatabaseInstance()); + sampleDAO.tryFindByCodeAndDatabaseInstance(sampleCode, + sampleOwner.tryGetDatabaseInstance()); } else { assert sampleOwner.isGroupLevel() : "Must be of space level."; diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleTable.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleTable.java index 7b3b58b875ba85f46cf8187eaf8e5abc42df2c48..50aacbf294a13c578df3150146dd32fb2068be13 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleTable.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleTable.java @@ -251,6 +251,14 @@ public final class SampleTable extends AbstractSampleBusinessObject implements I setGeneratedFrom(updates.getSampleIdentifier(), sample, updates.getParentIdentifierOrNull()); } + if (details.isParentsUpdateRequested()) + { + final String[] parents = updates.getModifiedParentCodesOrNull(); + if (parents != null) + { + setParents(sample, parents); + } + } if (details.isContainerUpdateRequested()) { setContainer(updates.getSampleIdentifier(), sample, @@ -258,7 +266,8 @@ public final class SampleTable extends AbstractSampleBusinessObject implements I } // NOTE: Checking business rules with relationships is expensive. // Don't perform them unless relevant data were changed. - if (details.isExperimentUpdateRequested() || details.isParentUpdateRequested()) + if (details.isExperimentUpdateRequested() || details.isParentUpdateRequested() + || details.isParentsUpdateRequested()) { checkParentBusinessRules(sample); } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewSample.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewSample.java index 4fd95b58100507e36fdfa890e2d8b26ceb6fd621..39dad9bdc5ff89cb4722f157ba4621eff7c8d988 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewSample.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewSample.java @@ -39,6 +39,8 @@ public class NewSample extends Identifier<NewSample> implements Comparable<NewSa public static final String PARENT = "parent"; + public static final String PARENTS = "parents"; + public static final String EXPERIMENT = "experiment"; private SampleType sampleType; @@ -97,11 +99,12 @@ public class NewSample extends Identifier<NewSample> implements Comparable<NewSa } public NewSample(final String identifier, SampleType sampleType, String containerIdentifier, - String parentIdentifier, String experimentIdentifier, IEntityProperty[] properties, - List<NewAttachment> attachments) + String parentIdentifier, String[] parentsOrNull, String experimentIdentifier, + IEntityProperty[] properties, List<NewAttachment> attachments) { this(identifier, sampleType, containerIdentifier); this.parentIdentifier = parentIdentifier; + this.parentsOrNull = parentsOrNull; this.experimentIdentifier = experimentIdentifier; this.properties = properties; this.attachments = attachments; @@ -137,6 +140,19 @@ public class NewSample extends Identifier<NewSample> implements Comparable<NewSa this.parentsOrNull = parents; } + @BeanProperty(label = PARENTS, optional = true) + public void setParents(String parents) + { + if (parents != null) + { + String[] split = parents.split(","); + setParents(split); + } else + { + setParents((String[]) null); + } + } + public final String getParentIdentifier() { return parentIdentifier; diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/RelationshipType.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/RelationshipType.java new file mode 100644 index 0000000000000000000000000000000000000000..478f951659a9d3840b09d37360c043404d2baa5d --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/RelationshipType.java @@ -0,0 +1,123 @@ +/* + * Copyright 2010 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.shared.basic.dto; + +import java.io.Serializable; + +import com.google.gwt.user.client.rpc.IsSerializable; + +/** + * The <i>GWT</i> version of RelationshipTypePE. + * + * @author Piotr Buczek + */ +public class RelationshipType extends Code<PropertyType> implements IsSerializable, Serializable +{ + private static final long serialVersionUID = ServiceVersionHolder.VERSION; + + private Long id; + + /** + * Only used for displaying/viewing. With <code>managedInternally</code> is unambiguous (meaning + * that <code>simpleCode</code> alone could be not unique). + * <p> + * We have to use it, partly because <i>Javascript</i> handle '.' in an object-oriented way. + * </p> + */ + private String simpleCode; + + private boolean internalNamespace; + + private boolean managedInternally; + + private String description; + + private String label; + + private DatabaseInstance databaseInstance; + + public Long getId() + { + return id; + } + + public void setId(Long id) + { + this.id = id; + } + + public String getSimpleCode() + { + return simpleCode; + } + + public void setSimpleCode(String simpleCode) + { + this.simpleCode = simpleCode; + } + + public boolean isInternalNamespace() + { + return internalNamespace; + } + + public void setInternalNamespace(boolean internalNamespace) + { + this.internalNamespace = internalNamespace; + } + + public boolean isManagedInternally() + { + return managedInternally; + } + + public void setManagedInternally(boolean managedInternally) + { + this.managedInternally = managedInternally; + } + + public String getDescription() + { + return description; + } + + public void setDescription(String description) + { + this.description = description; + } + + public String getLabel() + { + return label; + } + + public void setLabel(String label) + { + this.label = label; + } + + public DatabaseInstance getDatabaseInstance() + { + return databaseInstance; + } + + public void setDatabaseInstance(DatabaseInstance databaseInstance) + { + this.databaseInstance = databaseInstance; + } + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/SampleBatchUpdateDetails.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/SampleBatchUpdateDetails.java index a67c64b290d373761158a9e6d748980705122c84..246ba61e934dd6d7329e6c2f620377d174a8efb9 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/SampleBatchUpdateDetails.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/SampleBatchUpdateDetails.java @@ -34,6 +34,8 @@ public class SampleBatchUpdateDetails implements IsSerializable, Serializable private boolean parentUpdateRequested; + private boolean parentsUpdateRequested; + private boolean containerUpdateRequested; private Set<String> propertiesToUpdate; // codes of properties to update @@ -43,10 +45,11 @@ public class SampleBatchUpdateDetails implements IsSerializable, Serializable } public SampleBatchUpdateDetails(boolean updateExperiment, boolean updateParent, - boolean updateContainer, Set<String> propertiesToUpdate) + boolean updateParents, boolean updateContainer, Set<String> propertiesToUpdate) { this.experimentUpdateRequested = updateExperiment; this.parentUpdateRequested = updateParent; + this.parentsUpdateRequested = updateParents; this.containerUpdateRequested = updateContainer; this.propertiesToUpdate = propertiesToUpdate; } @@ -61,6 +64,11 @@ public class SampleBatchUpdateDetails implements IsSerializable, Serializable return parentUpdateRequested; } + public boolean isParentsUpdateRequested() + { + return parentsUpdateRequested; + } + public boolean isContainerUpdateRequested() { return containerUpdateRequested; diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/UpdatedSample.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/UpdatedSample.java index c028671370816ef1b291ebb5b65e6ba67fbd5c80..6a531d9baa29f0c93429636b79328348577e3cbf 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/UpdatedSample.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/UpdatedSample.java @@ -40,8 +40,9 @@ public final class UpdatedSample extends NewSample public UpdatedSample(NewSample newSample, SampleBatchUpdateDetails batchUpdateDetails) { super(newSample.getIdentifier(), newSample.getSampleType(), newSample - .getContainerIdentifier(), newSample.getParentIdentifier(), newSample - .getExperimentIdentifier(), newSample.getProperties(), newSample.getAttachments()); + .getContainerIdentifier(), newSample.getParentIdentifier(), newSample.getParents(), + newSample.getExperimentIdentifier(), newSample.getProperties(), newSample + .getAttachments()); this.batchUpdateDetails = batchUpdateDetails; } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/server/parser/UpdatedSampleParserObjectFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/server/parser/UpdatedSampleParserObjectFactory.java index 17558aa8b83083ed2a16380e086301cd16dd2057..51a94ce4e0940617bb3b3a4cf0209dbe51285de1 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/server/parser/UpdatedSampleParserObjectFactory.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/server/parser/UpdatedSampleParserObjectFactory.java @@ -54,9 +54,10 @@ final class UpdatedSampleParserObjectFactory extends NewSampleParserObjectFactor { boolean updateExperiment = isColumnAvailable(UpdatedSample.EXPERIMENT); boolean updateParent = isColumnAvailable(UpdatedSample.PARENT); + boolean updateParents = isColumnAvailable(UpdatedSample.PARENTS); boolean updateContainer = isColumnAvailable(UpdatedSample.CONTAINER); - return new SampleBatchUpdateDetails(updateExperiment, updateParent, updateContainer, - getUnmatchedProperties()); + return new SampleBatchUpdateDetails(updateExperiment, updateParent, updateParents, + updateContainer, getUnmatchedProperties()); } // @@ -88,6 +89,9 @@ final class UpdatedSampleParserObjectFactory extends NewSampleParserObjectFactor final boolean updateParent = basicBatchUpdateDetails.isParentUpdateRequested() && isNotEmpty(newSample.getParentIdentifier()); + final boolean updateParents = + basicBatchUpdateDetails.isParentsUpdateRequested() + && isNotEmpty(newSample.getParents()); final boolean updateContainer = basicBatchUpdateDetails.isContainerUpdateRequested() && isNotEmpty(newSample.getContainerIdentifier()); @@ -98,8 +102,13 @@ final class UpdatedSampleParserObjectFactory extends NewSampleParserObjectFactor propertiesToUpdate.add(property.getPropertyType().getCode()); } - return new SampleBatchUpdateDetails(updateExperiment, updateParent, updateContainer, - propertiesToUpdate); + return new SampleBatchUpdateDetails(updateExperiment, updateParent, updateParents, + updateContainer, propertiesToUpdate); + } + + private boolean isNotEmpty(String[] parents) + { + return parents != null && parents.length > 0 && isNotEmpty(parents[0]); } /** Cleans properties and connections of the specified sample that are marked for deletion. */ @@ -113,6 +122,10 @@ final class UpdatedSampleParserObjectFactory extends NewSampleParserObjectFactor { newSample.setParentIdentifier(null); } + if (newSample.getParents() != null && isDeletionMark(newSample.getParents()[0])) + { + newSample.setParents(new String[0]); + } if (isDeletionMark(newSample.getContainerIdentifier())) { newSample.setContainerIdentifier(null); diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServer.java index e7c8a5ba4e62936dfbbec6a9de0c8f9ad3829805..3e71b8aaba57fa3a2f48b874d59e5a8a668db29a 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServer.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServer.java @@ -481,7 +481,7 @@ public final class GenericServer extends AbstractServer<IGenericServer> implemen } final String parentIdentifierOrNull = updatedSample.getParentIdentifier(); final String[] parentsOrNull = - (parentIdentifierOrNull == null) ? new String[0] : new String[] + (parentIdentifierOrNull == null) ? updatedSample.getParents() : new String[] { parentIdentifierOrNull }; final String containerIdentifierOrNull = updatedSample.getContainerIdentifier(); final SampleBatchUpdateDetails batchUpdateDetails = @@ -508,7 +508,7 @@ public final class GenericServer extends AbstractServer<IGenericServer> implemen propertyCodes.add(p.getPropertyType().getCode()); } SampleBatchUpdateDetails result = - new SampleBatchUpdateDetails(false, false, false, propertyCodes); + new SampleBatchUpdateDetails(false, false, false, false, propertyCodes); return result; } }