From b21ab898f7f370d7df877f06a6985f1ccea4d3d5 Mon Sep 17 00:00:00 2001 From: izabel <izabel> Date: Wed, 2 Jun 2010 07:26:26 +0000 Subject: [PATCH] [LMS-1529] create wells on the fly when datasets are registered before the library is registered; allow to "update" already existing samples on "Library" registration SVN: 16251 --- .../ch/systemsx/cisd/bds/hcs/Location.java | 13 +++ .../systemsx/cisd/bds/hcs/LocationTest.java | 21 ++++ .../cisd/common/geometry/ConversionUtils.java | 15 +++ .../server/EncapsulatedOpenBISService.java | 9 ++ .../shared/IEncapsulatedOpenBISService.java | 7 ++ .../openbis/generic/server/ETLService.java | 93 +++++++++++++++ .../generic/server/ETLServiceLogger.java | 12 ++ .../authorization/PredicateExecutor.java | 6 + .../generic/shared/IETLLIMSService.java | 16 +++ .../IAuthorizationDataProvider.java | 6 + .../SampleComponentsDescriptionPredicate.java | 51 ++++++++ .../predicate/SamplePermIdPredicate.java | 74 ++++++++++++ .../openbis/generic/shared/basic/PermId.java | 94 +++++++++++++++ .../shared/basic/dto/NewSamplesWithTypes.java | 12 ++ .../dto/SampleComponentsDescription.java | 73 ++++++++++++ .../server/GenericBusinessObjectFactory.java | 7 ++ .../plugin/generic/server/GenericServer.java | 55 ++++++++- .../generic/server/GenericServerLogger.java | 15 +++ .../server/IGenericBusinessObjectFactory.java | 3 + .../server/SampleRegisterOrUpdateUtil.java | 110 ++++++++++++++++++ .../plugin/generic/shared/IGenericServer.java | 11 ++ .../shared/IETLLIMSService.java.expected | 16 +++ .../shared/IGenericServer.java.expected | 11 ++ .../openbis/dss/etl/HCSDatasetUploader.java | 61 +++++++--- .../dss/etl/dataaccess/IImagingUploadDAO.java | 4 +- .../dss/etl/dataaccess/ImgSpotDTO.java | 16 ++- .../client/web/server/LibraryExtractor.java | 12 +- .../web/server/LibraryRegistrationTask.java | 2 +- .../shared/basic/dto/ScreeningConstants.java | 4 + .../source/sql/postgresql/001/schema-001.sql | 2 + .../etl/dataaccess/ImagingUploadDAOTest.java | 3 + 31 files changed, 814 insertions(+), 20 deletions(-) create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/SampleComponentsDescriptionPredicate.java create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/SamplePermIdPredicate.java create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/PermId.java create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SampleComponentsDescription.java create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/SampleRegisterOrUpdateUtil.java diff --git a/bds/source/java/ch/systemsx/cisd/bds/hcs/Location.java b/bds/source/java/ch/systemsx/cisd/bds/hcs/Location.java index 9641a1729c2..6f7ad4509e0 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/hcs/Location.java +++ b/bds/source/java/ch/systemsx/cisd/bds/hcs/Location.java @@ -92,6 +92,19 @@ public final class Location } } + /** + * For given location returns corresponding matrix coordinate. + */ + public static final String tryCreateMatrixCoordinateFromLocation(final Location location) + { + if (location == null) + { + throw new IllegalArgumentException("Location unspecified"); + } + Point point = new Point(location.getY() - 1, location.getX() - 1); + return ConversionUtils.convertToSpreadsheetLocation(point); + } + // // Object // diff --git a/bds/sourceTest/java/ch/systemsx/cisd/bds/hcs/LocationTest.java b/bds/sourceTest/java/ch/systemsx/cisd/bds/hcs/LocationTest.java index 7e3cb097282..8b072e1054c 100644 --- a/bds/sourceTest/java/ch/systemsx/cisd/bds/hcs/LocationTest.java +++ b/bds/sourceTest/java/ch/systemsx/cisd/bds/hcs/LocationTest.java @@ -101,4 +101,25 @@ public final class LocationTest assertEquals(new Location(7, 26), Location.tryCreateLocationFromMatrixCoordinate("z7")); assertEquals(new Location(34, 15), Location.tryCreateLocationFromMatrixCoordinate("O34")); } + + @Test + public final void testCreateMatrixCoordinateFromLocation() + { + assertEquals("A1", Location.tryCreateMatrixCoordinateFromLocation(new Location(1, 1))); + assertEquals("A2", Location.tryCreateMatrixCoordinateFromLocation(new Location(2, 1))); + assertEquals("Z7", Location.tryCreateMatrixCoordinateFromLocation(new Location(7, 26))); + assertEquals("O34", Location.tryCreateMatrixCoordinateFromLocation(new Location(34, 15))); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public final void testCreateMatrixCoordinateFromTooBigNumber() + { + Location.tryCreateMatrixCoordinateFromLocation(new Location(134, 27)); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public final void testCreateMatrixCoordinateFromNullLocation() + { + Location.tryCreateMatrixCoordinateFromLocation(null); + } } diff --git a/common/source/java/ch/systemsx/cisd/common/geometry/ConversionUtils.java b/common/source/java/ch/systemsx/cisd/common/geometry/ConversionUtils.java index 3c0d8e92b43..a07404e2d33 100644 --- a/common/source/java/ch/systemsx/cisd/common/geometry/ConversionUtils.java +++ b/common/source/java/ch/systemsx/cisd/common/geometry/ConversionUtils.java @@ -90,6 +90,21 @@ public class ConversionUtils } + static public String convertToSpreadsheetLocation(Point p) + { + if (p == null) + { + throw new IllegalArgumentException("Unspecified point."); + } + if (p.getX() >= 26 || p.getX() < 0) + { + throw new IllegalArgumentException("Unsupported value: " + p.getX()); + } + char x = (char) (p.getX() + 'A'); + int y = p.getY() + 1; + return String.format("%s%s", x, y); + } + private static int getLetterNumber(final char ch) { return Character.toUpperCase(ch) - 'A' + 1; diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISService.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISService.java index 50f357308a1..b4df1ab81f4 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISService.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISService.java @@ -17,6 +17,8 @@ package ch.systemsx.cisd.openbis.dss.generic.server; import java.util.List; +import java.util.Map; +import java.util.Set; import org.apache.log4j.Logger; import org.springframework.beans.factory.FactoryBean; @@ -52,6 +54,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.DatastoreServiceDescriptions; import ch.systemsx.cisd.openbis.generic.shared.dto.ListSamplesByPropertyCriteria; import ch.systemsx.cisd.openbis.generic.shared.dto.NewExternalData; import ch.systemsx.cisd.openbis.generic.shared.dto.NewProperty; +import ch.systemsx.cisd.openbis.generic.shared.dto.SampleComponentsDescription; import ch.systemsx.cisd.openbis.generic.shared.dto.SampleUpdatesDTO; import ch.systemsx.cisd.openbis.generic.shared.dto.SessionContextDTO; import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO; @@ -697,4 +700,10 @@ public final class EncapsulatedOpenBISService implements IEncapsulatedOpenBISSer { service.unarchiveDatasets(sessionToken, dataSetCodes); } + + public Map<String, String> listOrRegisterComponents(String containerPermId, Set<String> codes, + String sampleTypeCode) throws UserFailureException + { + return service.listOrRegisterComponents(sessionToken, new SampleComponentsDescription(containerPermId, codes, sampleTypeCode)); + } } \ No newline at end of file diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/IEncapsulatedOpenBISService.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/IEncapsulatedOpenBISService.java index 0d87d03d0c0..aefe20cecb5 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/IEncapsulatedOpenBISService.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/IEncapsulatedOpenBISService.java @@ -17,6 +17,8 @@ package ch.systemsx.cisd.openbis.dss.generic.shared; import java.util.List; +import java.util.Map; +import java.util.Set; import ch.systemsx.cisd.common.exceptions.UserFailureException; import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation; @@ -38,6 +40,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType; import ch.systemsx.cisd.openbis.generic.shared.dto.ListSamplesByPropertyCriteria; import ch.systemsx.cisd.openbis.generic.shared.dto.NewExternalData; import ch.systemsx.cisd.openbis.generic.shared.dto.NewProperty; +import ch.systemsx.cisd.openbis.generic.shared.dto.SampleComponentsDescription; import ch.systemsx.cisd.openbis.generic.shared.dto.SampleUpdatesDTO; import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier; @@ -223,4 +226,8 @@ public interface IEncapsulatedOpenBISService /** See {@link IETLLIMSService#checkSpaceAccess(String, SpaceIdentifier)} */ public void checkSpaceAccess(String sToken, SpaceIdentifier spaceId); + + /** See {@link IETLLIMSService#listOrRegisterComponents(String, SampleComponentsDescription)} */ + public Map<String, String> listOrRegisterComponents(final String containerPermId, + Set<String> codes, String sampleTypeCode) throws UserFailureException; } \ No newline at end of file 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 e0a4d496a16..4dfbea3e51e 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 @@ -18,10 +18,12 @@ package ch.systemsx.cisd.openbis.generic.server; import static ch.systemsx.cisd.openbis.generic.shared.GenericSharedConstants.DATA_STORE_SERVER_WEB_APPLICATION_NAME; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import ch.systemsx.cisd.authentication.IAuthenticationService; @@ -84,6 +86,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.NewExternalData; import ch.systemsx.cisd.openbis.generic.shared.dto.NewProperty; import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE; import ch.systemsx.cisd.openbis.generic.shared.dto.PropertyTypePE; +import ch.systemsx.cisd.openbis.generic.shared.dto.SampleComponentsDescription; import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE; import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePropertyPE; import ch.systemsx.cisd.openbis.generic.shared.dto.SampleTypePE; @@ -705,4 +708,94 @@ public class ETLService extends AbstractCommonServer<IETLService> implements IET return url; } + + public Map<String, String> listOrRegisterComponents(String sessionToken, + SampleComponentsDescription components) throws UserFailureException + { + assert sessionToken != null : "Unspecified session token."; + assert components != null : "Unspecified components."; + + final Session session = getSession(sessionToken); + SamplePE container = getContainer(components.getContainerPermId()); + Set<String> codesToGet = new HashSet<String>(components.getCodes()); + Map<String, String> result = new HashMap<String, String>(); + tryLoadSamples(session, listSamplesForContainer(session, container), codesToGet, result); + if (codesToGet.size() > 0) + { + registerSamples(components.getSampleTypeCode(), session, container, codesToGet); + tryLoadSamples(session, listSamplesForContainer(session, container), codesToGet, result); + } + assert codesToGet.size() == 0 : "All samples should exist at this point"; + return result; + } + + private void registerSamples(String sampleTypeCode, final Session session, SamplePE container, + Set<String> codesToGet) + { + final SampleTypePE sampleTypePE = getSampleType(sampleTypeCode); + List<NewSample> newSamples = new ArrayList<NewSample>(); + for (String code : codesToGet) + { + String groupPrefix = + container.getGroup() != null ? ("/" + container.getGroup().getCode() + "/") + : "/"; + newSamples.add(new NewSample(groupPrefix + code, SampleTypeTranslator.translate( + sampleTypePE, null), null, container.getIdentifier())); + } + getSampleTypeSlaveServerPlugin(sampleTypePE).registerSamples(session, newSamples); + } + + private SamplePE getContainer(String containerPermId) + { + SamplePE container = daoFactory.getSampleDAO().tryToFindByPermID(containerPermId); + if (container == null) + { + throw new UserFailureException(String.format("Container '%s' not found.", + containerPermId)); + } + return container; + } + + List<Sample> listSamplesForContainer(Session session, SamplePE container) + { + ListOrSearchSampleCriteria criteria = createListSamplesByContainerCriteria(container); + return businessObjectFactory.createSampleLister(session).list(criteria); + } + + private SampleTypePE getSampleType(String sampleTypeCode) + { + final SampleTypePE sampleTypePE = + getDAOFactory().getSampleTypeDAO().tryFindSampleTypeByCode(sampleTypeCode); + if (sampleTypePE == null) + { + throw UserFailureException.fromTemplate("Sample type with code '%s' does not exist.", + sampleTypeCode); + } + return sampleTypePE; + } + + private static ListOrSearchSampleCriteria createListSamplesByContainerCriteria( + SamplePE container) + { + ListOrSearchSampleCriteria criteria = + new ListOrSearchSampleCriteria(ListOrSearchSampleCriteria + .createForContainer(new TechId(container.getId()))); + criteria.setEnrichDependentSamplesWithProperties(false); + return criteria; + } + + private static void tryLoadSamples(final Session session, List<Sample> samples, + Set<String> codesToGet, Map<String, String> result) + { + for (Sample s : samples) + { + String subCode = s.getSubCode(); + if (codesToGet.contains(subCode)) + { + result.put(subCode, s.getPermId()); + codesToGet.remove(subCode); + } + } + } + } 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 1392463bf4f..35b409bb47c 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 @@ -17,6 +17,7 @@ package ch.systemsx.cisd.openbis.generic.server; import java.util.List; +import java.util.Map; import ch.systemsx.cisd.authentication.ISessionManager; import ch.systemsx.cisd.common.exceptions.UserFailureException; @@ -41,6 +42,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.DatastoreServiceDescriptions; import ch.systemsx.cisd.openbis.generic.shared.dto.ListSamplesByPropertyCriteria; import ch.systemsx.cisd.openbis.generic.shared.dto.NewExternalData; import ch.systemsx.cisd.openbis.generic.shared.dto.NewProperty; +import ch.systemsx.cisd.openbis.generic.shared.dto.SampleComponentsDescription; import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE; import ch.systemsx.cisd.openbis.generic.shared.dto.SampleUpdatesDTO; import ch.systemsx.cisd.openbis.generic.shared.dto.Session; @@ -276,4 +278,14 @@ public class ETLServiceLogger extends AbstractServerLogger implements IETLServic logAccess(sessionToken, "getDefaultDataStoreBaseURL"); return null; } + + public Map<String, String> listOrRegisterComponents(String sessionToken, + SampleComponentsDescription components) + throws UserFailureException + { + logTracking(sessionToken, "listOrRegisterComponents", "CONTAINER(%s) CODES(%s) TYPE(%s)", + components.getContainerPermId(), components.getCodes().size(), components.getSampleTypeCode()); + + return null; + } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/PredicateExecutor.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/PredicateExecutor.java index 32a166434b6..e14b13d96a0 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/PredicateExecutor.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/PredicateExecutor.java @@ -34,6 +34,7 @@ import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.ShouldFl import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.ArrayPredicate; import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.CollectionPredicate; import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.IPredicate; +import ch.systemsx.cisd.openbis.generic.shared.basic.PermId; import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE; import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetAccessPE; @@ -331,6 +332,11 @@ public final class PredicateExecutor return daoFactory.getSampleDAO().getByTechId(techId); } + public SamplePE getSample(PermId id) + { + return daoFactory.getSampleDAO().tryToFindByPermID(id.getId()); + } + public GridCustomFilterPE getGridCustomFilter(TechId techId) { return daoFactory.getGridCustomFilterDAO().getByTechId(techId); 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 46d3c841541..32900ffa715 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 @@ -17,6 +17,7 @@ package ch.systemsx.cisd.openbis.generic.shared; import java.util.List; +import java.util.Map; import org.springframework.transaction.annotation.Transactional; @@ -32,6 +33,7 @@ import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.ListSampl import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.ListSamplesByPropertyPredicate; import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.NewExperimentPredicate; import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.NewSamplePredicate; +import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.SampleComponentsDescriptionPredicate; import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.SampleOwnerIdentifierPredicate; import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.SampleTechIdPredicate; import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.SampleUpdatesPredicate; @@ -58,6 +60,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.DataStoreServerInfo; import ch.systemsx.cisd.openbis.generic.shared.dto.ListSamplesByPropertyCriteria; import ch.systemsx.cisd.openbis.generic.shared.dto.NewExternalData; import ch.systemsx.cisd.openbis.generic.shared.dto.NewProperty; +import ch.systemsx.cisd.openbis.generic.shared.dto.SampleComponentsDescription; import ch.systemsx.cisd.openbis.generic.shared.dto.SampleUpdatesDTO; import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier; @@ -407,4 +410,17 @@ public interface IETLLIMSService extends IServer, ISessionProvider @RolesAllowed(RoleSet.USER) public void checkSpaceAccess(String sessionToken, @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class) SpaceIdentifier spaceId); + + /** + * Load perm ids of samples contained in given container. Register samples that don't exist. + * + */ + @Transactional + @RolesAllowed(RoleSet.ETL_SERVER) + @DatabaseCreateOrDeleteModification(value = ObjectKind.SAMPLE) + public Map<String, String> listOrRegisterComponents( + final String sessionToken, + @AuthorizationGuard(guardClass = SampleComponentsDescriptionPredicate.class) SampleComponentsDescription components) + throws UserFailureException; + } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/IAuthorizationDataProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/IAuthorizationDataProvider.java index c7e3fb51d84..66de4b37e1b 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/IAuthorizationDataProvider.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/IAuthorizationDataProvider.java @@ -19,6 +19,7 @@ package ch.systemsx.cisd.openbis.generic.shared.authorization; import java.util.List; import ch.systemsx.cisd.openbis.generic.shared.IDatabaseInstanceFinder; +import ch.systemsx.cisd.openbis.generic.shared.basic.PermId; import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetAccessPE; import ch.systemsx.cisd.openbis.generic.shared.dto.GridCustomColumnPE; @@ -69,6 +70,11 @@ public interface IAuthorizationDataProvider extends IDatabaseInstanceFinder */ public SamplePE getSample(TechId techId); + /** + * Returns the sample with given <var>permId</var>. + */ + public SamplePE getSample(PermId id); + /** * Returns the filter with given <var>techId</var> */ diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/SampleComponentsDescriptionPredicate.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/SampleComponentsDescriptionPredicate.java new file mode 100644 index 00000000000..1ff04eab3a6 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/SampleComponentsDescriptionPredicate.java @@ -0,0 +1,51 @@ +/* + * 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.shared.authorization.predicate; + +import ch.systemsx.cisd.openbis.generic.shared.basic.PermId; +import ch.systemsx.cisd.openbis.generic.shared.dto.SampleComponentsDescription; + +/** + * An <code>IPredicate</code> implementation for {@link SampleComponentsDescription}. + * + * @author Izabela Adamczyk + */ +public final class SampleComponentsDescriptionPredicate extends + DelegatedPredicate<PermId, SampleComponentsDescription> +{ + public SampleComponentsDescriptionPredicate() + { + super(new SamplePermIdPredicate()); + } + + // + // DelegatedPredicate + // + + @Override + public final PermId convert(final SampleComponentsDescription value) + { + return new PermId(value.getContainerPermId()); + } + + @Override + public final String getCandidateDescription() + { + return "new sample"; + } + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/SamplePermIdPredicate.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/SamplePermIdPredicate.java new file mode 100644 index 00000000000..4a9a0214a8d --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/predicate/SamplePermIdPredicate.java @@ -0,0 +1,74 @@ +/* + * Copyright 2009 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.authorization.predicate; + +import java.util.List; + +import ch.systemsx.cisd.common.exceptions.Status; +import ch.systemsx.cisd.openbis.generic.shared.authorization.IAuthorizationDataProvider; +import ch.systemsx.cisd.openbis.generic.shared.authorization.RoleWithIdentifier; +import ch.systemsx.cisd.openbis.generic.shared.basic.PermId; +import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE; +import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE; + +/** + * An <code>IPredicate</code> implementation based on permId of a sample. + * + * @author Izabela Adamczyk + */ +public class SamplePermIdPredicate extends AbstractDatabaseInstancePredicate<PermId> +{ + + private final SampleOwnerIdentifierPredicate sampleOwnerIdentifierPredicate; + + public SamplePermIdPredicate() + { + this(true); + } + + public SamplePermIdPredicate(boolean isReadAccess) + { + sampleOwnerIdentifierPredicate = new SampleOwnerIdentifierPredicate(isReadAccess); + } + + // + // AbstractPredicate + // + + @Override + public final void init(IAuthorizationDataProvider provider) + { + super.init(provider); + sampleOwnerIdentifierPredicate.init(provider); + } + + @Override + public final String getCandidateDescription() + { + return "sample perm id"; + } + + @Override + final Status doEvaluation(final PersonPE person, final List<RoleWithIdentifier> allowedRoles, + final PermId id) + { + SamplePE sample = authorizationDataProvider.getSample(id); + return sampleOwnerIdentifierPredicate.doEvaluation(person, allowedRoles, sample + .getSampleIdentifier()); + } + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/PermId.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/PermId.java new file mode 100644 index 00000000000..ee8a21427f4 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/PermId.java @@ -0,0 +1,94 @@ +/* + * Copyright 2009 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; + +import java.io.Serializable; + +import com.google.gwt.user.client.rpc.IsSerializable; + +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder; + +/** + * Perm id of an entity. + * + * @author Izabela Adamczyk + */ +public class PermId implements IsSerializable, Serializable +{ + private static final long serialVersionUID = ServiceVersionHolder.VERSION; + + private String id; + + protected PermId() + { + // for serialization + } + + public PermId(String id) + { + assert id != null : "id cannot be null"; + this.id = id; + } + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + + public static PermId create(IPermIdHolder holder) + { + if (holder == null || holder.getPermId() == null) + { + return null; + } else + { + return new PermId(holder.getPermId()); + } + } + + @Override + public final boolean equals(final Object obj) + { + if (obj == this) + { + return true; + } + if (obj instanceof PermId == false) + { + return false; + } + return this.toString().equals(obj.toString()); + } + + @Override + public final int hashCode() + { + return this.toString().hashCode(); + } + + @Override + public String toString() + { + return id; + } + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewSamplesWithTypes.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewSamplesWithTypes.java index 4215e1ea27e..3c472c69c5e 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewSamplesWithTypes.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewSamplesWithTypes.java @@ -29,6 +29,18 @@ public class NewSamplesWithTypes List<NewSample> newSamples; + boolean allowUpdateIfExist = false; + + public boolean isAllowUpdateIfExist() + { + return allowUpdateIfExist; + } + + public void setAllowUpdateIfExist(boolean allowUpdateIfExist) + { + this.allowUpdateIfExist = allowUpdateIfExist; + } + public NewSamplesWithTypes() { } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SampleComponentsDescription.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SampleComponentsDescription.java new file mode 100644 index 00000000000..2a62309b960 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SampleComponentsDescription.java @@ -0,0 +1,73 @@ +/* + * 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.dto; + +import java.io.Serializable; +import java.util.Set; + +import com.google.gwt.user.client.rpc.IsSerializable; + +import ch.systemsx.cisd.openbis.generic.shared.IServer; + +/** + * Stores basic information about sample components. + * + * @author Izabela Adamczyk + */ +public class SampleComponentsDescription implements IsSerializable, Serializable +{ + private static final long serialVersionUID = IServer.VERSION; + + private final String containerPermId; + + private Set<String> codes; + + private String sampleTypeCode; + + public SampleComponentsDescription(String containerPermId, Set<String> codes, + String sampleTypeCode) + { + this.containerPermId = containerPermId; + this.codes = codes; + this.sampleTypeCode = sampleTypeCode; + } + + public String getContainerPermId() + { + return containerPermId; + } + + public Set<String> getCodes() + { + return codes; + } + + public void setCodes(Set<String> codes) + { + this.codes = codes; + } + + public String getSampleTypeCode() + { + return sampleTypeCode; + } + + public void setSampleTypeCode(String sampleTypeCode) + { + this.sampleTypeCode = sampleTypeCode; + } +} \ No newline at end of file diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericBusinessObjectFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericBusinessObjectFactory.java index a3c7049fd9c..b80b50c230f 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericBusinessObjectFactory.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericBusinessObjectFactory.java @@ -26,6 +26,8 @@ import ch.systemsx.cisd.openbis.generic.server.business.bo.IMaterialTable; import ch.systemsx.cisd.openbis.generic.server.business.bo.IProjectBO; import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleBO; import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleTable; +import ch.systemsx.cisd.openbis.generic.server.business.bo.samplelister.ISampleLister; +import ch.systemsx.cisd.openbis.generic.server.business.bo.samplelister.SampleLister; import ch.systemsx.cisd.openbis.generic.shared.dto.Session; import ch.systemsx.cisd.openbis.plugin.AbstractPluginBusinessObjectFactory; import ch.systemsx.cisd.openbis.plugin.generic.shared.ResourceNames; @@ -83,4 +85,9 @@ public final class GenericBusinessObjectFactory extends AbstractPluginBusinessOb { return getCommonBusinessObjectFactory().createProjectBO(session); } + + public ISampleLister createSampleLister(Session session) + { + return SampleLister.create(getDaoFactory(), session.getBaseIndexURL()); + } } 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 dd938ccd1c9..1edcea074df 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 @@ -24,6 +24,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import javax.annotation.Resource; @@ -63,6 +64,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewExperiment; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewMaterial; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSamplesWithTypes; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleBatchUpdateDetails; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleParentWithDerived; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType; @@ -253,6 +255,38 @@ public final class GenericServer extends AbstractServer<IGenericServer> implemen filename, version)); } + public final void registerOrUpdateSamples(final String sessionToken, + final List<NewSamplesWithTypes> newSamplesWithType) throws UserFailureException + { + assert sessionToken != null : "Unspecified session token."; + final Session session = getSession(sessionToken); + for (NewSamplesWithTypes samples : newSamplesWithType) + { + if (samples.isAllowUpdateIfExist() == false) + { + registerSamples(session, samples); + } else + { + registerOrUpdate(session, samples); + } + } + } + + private void registerOrUpdate(final Session session, NewSamplesWithTypes samples) + { + List<Sample> existingSamples = + businessObjectFactory.createSampleLister(session).list( + SampleRegisterOrUpdateUtil.createListSamplesByCodeCriteria(samples + .getNewSamples())); + List<NewSample> samplesToUpdate = + SampleRegisterOrUpdateUtil.getSamplesToUpdate(samples, existingSamples); + List<NewSample> samplesToRegister = new ArrayList<NewSample>(samples.getNewSamples()); + samplesToRegister.removeAll(samplesToUpdate); + registerSamples(session, + new NewSamplesWithTypes(samples.getSampleType(), samplesToRegister)); + updateSamples(session, new NewSamplesWithTypes(samples.getSampleType(), samplesToUpdate)); + } + public final void registerSamples(final String sessionToken, final List<NewSamplesWithTypes> newSamplesWithType) throws UserFailureException { @@ -368,7 +402,7 @@ public final class GenericServer extends AbstractServer<IGenericServer> implemen final String parentIdentifierOrNull = updatedSample.getParentIdentifier(); final String containerIdentifierOrNull = updatedSample.getContainerIdentifier(); final SampleBatchUpdateDetails batchUpdateDetails = - ((UpdatedSample) updatedSample).getBatchUpdateDetails(); + createBatchUpdateDetails(updatedSample); batchUpdateSample(session, new SampleBatchUpdatesDTO(oldSampleIdentifier, properties, experimentIdentifierOrNull, newSampleIdentifier, parentIdentifierOrNull, @@ -376,6 +410,25 @@ public final class GenericServer extends AbstractServer<IGenericServer> implemen } } + SampleBatchUpdateDetails createBatchUpdateDetails(NewSample sample) + { + if (sample instanceof UpdatedSample) + { + return ((UpdatedSample) sample).getBatchUpdateDetails(); + } else + { + IEntityProperty[] properties = sample.getProperties(); + Set<String> propertyCodes = new HashSet<String>(); + for (IEntityProperty p : properties) + { + propertyCodes.add(p.getPropertyType().getCode()); + } + SampleBatchUpdateDetails result = + new SampleBatchUpdateDetails(false, false, false, propertyCodes); + return result; + } + } + public void registerExperiment(String sessionToken, NewExperiment newExperiment, final Collection<NewAttachment> attachments) { diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServerLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServerLogger.java index de1ea77f53b..53df577d8cd 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServerLogger.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServerLogger.java @@ -233,4 +233,19 @@ final class GenericServerLogger extends AbstractServerLogger implements IGeneric materialTypeCode, materials.size()); } + public void registerOrUpdateSamples(String sessionToken, + List<NewSamplesWithTypes> newSamplesWithType) throws UserFailureException + { + StringBuilder sb = new StringBuilder(); + for (NewSamplesWithTypes s : newSamplesWithType) + { + if (sb.length() > 0) + { + sb.append(","); + } + sb.append(s.getSampleType().getCode() + ":" + s.getNewSamples().size()); + } + logTracking(sessionToken, "register_or_update_samples", sb.toString()); + } + } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/IGenericBusinessObjectFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/IGenericBusinessObjectFactory.java index 46d8ca1ec6e..9e7339c8765 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/IGenericBusinessObjectFactory.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/IGenericBusinessObjectFactory.java @@ -24,6 +24,7 @@ import ch.systemsx.cisd.openbis.generic.server.business.bo.IMaterialTable; import ch.systemsx.cisd.openbis.generic.server.business.bo.IProjectBO; import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleBO; import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleTable; +import ch.systemsx.cisd.openbis.generic.server.business.bo.samplelister.ISampleLister; import ch.systemsx.cisd.openbis.generic.shared.dto.Session; /** @@ -72,4 +73,6 @@ public interface IGenericBusinessObjectFactory * Creates a {@link IExternalDataTable} <i>Business Object</i>. */ public IExternalDataTable createExternalDataTable(final Session session); + + public ISampleLister createSampleLister(Session session); } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/SampleRegisterOrUpdateUtil.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/SampleRegisterOrUpdateUtil.java new file mode 100644 index 00000000000..1a6748dd991 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/SampleRegisterOrUpdateUtil.java @@ -0,0 +1,110 @@ +/* + * 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.plugin.generic.server; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang.StringUtils; + +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListOrSearchSampleCriteria; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSamplesWithTypes; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample; +import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier; +import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFactory; + +/** + * Utility class for sample update or registration. + * + * @author Izabela Adamczyk + */ +public class SampleRegisterOrUpdateUtil +{ + private static final String INSTANCE_SEPARATOR = "/"; + + /** + * Returns a list of samples that already exist and should be updated. + */ + static List<NewSample> getSamplesToUpdate(NewSamplesWithTypes samples, + List<Sample> existingSamples) + { + List<NewSample> samplesToUpdate = new ArrayList<NewSample>(); + for (NewSample ns : samples.getNewSamples()) + { + for (Sample es : existingSamples) + { + if (isMatching(ns.getIdentifier(), es.getIdentifier())) + { + samplesToUpdate.add(ns); + } + } + } + return samplesToUpdate; + } + + /** + * Creates {@link ListOrSearchSampleCriteria} narrowing listing result to samples given codes. + */ + static ListOrSearchSampleCriteria createListSamplesByCodeCriteria(List<NewSample> samples) + { + List<String> codes = new ArrayList<String>(); + for (NewSample s : samples) + { + codes.add(extractCodeForSampleListingCriteria(s)); + } + String[] codesAsArray = codes.toArray(new String[0]); + ListOrSearchSampleCriteria criteria = new ListOrSearchSampleCriteria(codesAsArray); + return criteria; + } + + /** + * Checks if given identifiers are matching (db instance is not considered). + */ + private static boolean isMatching(String i1, String i2) + { + if (i1 != null && i2 != null) + { + return dropDatabaseInstance(i1).equals(dropDatabaseInstance(i2)); + } else + { + return i1 == i2; + } + } + + private static String dropDatabaseInstance(String id) + { + assert id != null; + assert id.contains(INSTANCE_SEPARATOR); + if (id.startsWith(INSTANCE_SEPARATOR)) + { + return id; + } else + { + return id.substring(id.indexOf(INSTANCE_SEPARATOR)); + } + + } + + private static String extractCodeForSampleListingCriteria(NewSample s) + { + SampleIdentifier parsedIdentifier = SampleIdentifierFactory.parse(s.getIdentifier()); + String subcode = parsedIdentifier.getSampleSubCode(); + String code = parsedIdentifier.getSampleCode(); + return StringUtils.isBlank(subcode) ? code : subcode; + } +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java index 1905503bc5b..8c04589f6a5 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java @@ -143,6 +143,17 @@ public interface IGenericServer extends IServer @AuthorizationGuard(guardClass = NewSamplesWithTypePredicate.class) final List<NewSamplesWithTypes> newSamplesWithType) throws UserFailureException; + /** + * Registers or updates samples of different types in batches. + */ + @Transactional + @RolesAllowed(RoleSet.USER) + @DatabaseCreateOrDeleteModification(value = ObjectKind.SAMPLE) + public void registerOrUpdateSamples( + final String sessionToken, + @AuthorizationGuard(guardClass = NewSamplesWithTypePredicate.class) final List<NewSamplesWithTypes> newSamplesWithType) + throws UserFailureException; + /** * Updates samples of different types in batches. */ 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 46d3c841541..32900ffa715 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 @@ -17,6 +17,7 @@ package ch.systemsx.cisd.openbis.generic.shared; import java.util.List; +import java.util.Map; import org.springframework.transaction.annotation.Transactional; @@ -32,6 +33,7 @@ import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.ListSampl import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.ListSamplesByPropertyPredicate; import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.NewExperimentPredicate; import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.NewSamplePredicate; +import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.SampleComponentsDescriptionPredicate; import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.SampleOwnerIdentifierPredicate; import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.SampleTechIdPredicate; import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.SampleUpdatesPredicate; @@ -58,6 +60,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.DataStoreServerInfo; import ch.systemsx.cisd.openbis.generic.shared.dto.ListSamplesByPropertyCriteria; import ch.systemsx.cisd.openbis.generic.shared.dto.NewExternalData; import ch.systemsx.cisd.openbis.generic.shared.dto.NewProperty; +import ch.systemsx.cisd.openbis.generic.shared.dto.SampleComponentsDescription; import ch.systemsx.cisd.openbis.generic.shared.dto.SampleUpdatesDTO; import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier; @@ -407,4 +410,17 @@ public interface IETLLIMSService extends IServer, ISessionProvider @RolesAllowed(RoleSet.USER) public void checkSpaceAccess(String sessionToken, @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class) SpaceIdentifier spaceId); + + /** + * Load perm ids of samples contained in given container. Register samples that don't exist. + * + */ + @Transactional + @RolesAllowed(RoleSet.ETL_SERVER) + @DatabaseCreateOrDeleteModification(value = ObjectKind.SAMPLE) + public Map<String, String> listOrRegisterComponents( + final String sessionToken, + @AuthorizationGuard(guardClass = SampleComponentsDescriptionPredicate.class) SampleComponentsDescription components) + throws UserFailureException; + } diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java.expected b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java.expected index 1905503bc5b..8c04589f6a5 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java.expected +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java.expected @@ -143,6 +143,17 @@ public interface IGenericServer extends IServer @AuthorizationGuard(guardClass = NewSamplesWithTypePredicate.class) final List<NewSamplesWithTypes> newSamplesWithType) throws UserFailureException; + /** + * Registers or updates samples of different types in batches. + */ + @Transactional + @RolesAllowed(RoleSet.USER) + @DatabaseCreateOrDeleteModification(value = ObjectKind.SAMPLE) + public void registerOrUpdateSamples( + final String sessionToken, + @AuthorizationGuard(guardClass = NewSamplesWithTypePredicate.class) final List<NewSamplesWithTypes> newSamplesWithType) + throws UserFailureException; + /** * Updates samples of different types in batches. */ diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/HCSDatasetUploader.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/HCSDatasetUploader.java index 6bb1120e837..48063b947ad 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/HCSDatasetUploader.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/HCSDatasetUploader.java @@ -18,11 +18,13 @@ package ch.systemsx.cisd.openbis.dss.etl; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Map.Entry; +import ch.systemsx.cisd.bds.hcs.Location; import ch.systemsx.cisd.common.exceptions.UserFailureException; import ch.systemsx.cisd.openbis.dss.etl.HCSImageFileExtractionResult.Channel; import ch.systemsx.cisd.openbis.dss.etl.dataaccess.IImagingUploadDAO; @@ -33,6 +35,9 @@ import ch.systemsx.cisd.openbis.dss.etl.dataaccess.ImgContainerDTO; import ch.systemsx.cisd.openbis.dss.etl.dataaccess.ImgDatasetDTO; import ch.systemsx.cisd.openbis.dss.etl.dataaccess.ImgImageDTO; import ch.systemsx.cisd.openbis.dss.etl.dataaccess.ImgSpotDTO; +import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; +import ch.systemsx.cisd.openbis.dss.generic.shared.ServiceProvider; +import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ScreeningConstants; /** * @author Tomasz Pylak @@ -127,17 +132,17 @@ class HCSDatasetUploader throw createInvalidNewChannelException(expId, existingChannels, channelName); } // a channel with a specified name already exists for an experiment, its description - // will be updated + // will be updated if (existingChannel.getWavelength().equals(channelDTO.getWavelength()) == false) - { + { throw UserFailureException.fromTemplate( - "There are already datasets registered for the experiment " - + "which use the same channel name, but with a different wavelength! " + "There are already datasets registered for the experiment " + + "which use the same channel name, but with a different wavelength! " + "Channel %s, old wavelength %d, new wavelength %d.", channelName, existingChannel.getWavelength(), channelDTO.getWavelength()); - } - channelDTO.setId(existingChannel.getId()); - dao.updateChannel(channelDTO); + } + channelDTO.setId(existingChannel.getId()); + dao.updateChannel(channelDTO); return channelDTO; } @@ -153,10 +158,10 @@ class HCSDatasetUploader } private ImgChannelDTO createChannel(long expId, HCSImageFileExtractionResult.Channel channel) - { + { ImgChannelDTO channelDTO = makeChannelDTO(channel, expId); - long channelId = dao.addChannel(channelDTO); - channelDTO.setId(channelId); + long channelId = dao.addChannel(channelDTO); + channelDTO.setId(channelId); return channelDTO; } @@ -285,16 +290,17 @@ class HCSDatasetUploader List<ImgSpotDTO> oldSpots = dao.listSpots(contId); List<ImgSpotDTO> newSpots = createNewSpots(contId, images, oldSpots, info.getContainerRows(), info - .getContainerColumns()); + .getContainerColumns(), info.getContainerPermId()); newSpots.addAll(oldSpots); return makeTechIdMatrix(newSpots, info.getContainerRows(), info.getContainerColumns()); } private List<ImgSpotDTO> createNewSpots(long contId, List<AcquiredPlateImage> images, - List<ImgSpotDTO> existingSpots, int rows, int columns) + List<ImgSpotDTO> existingSpots, int rows, int columns, String containerPermId) { Boolean[][] newSpotMatrix = extractNewSpots(rows, columns, images, existingSpots); List<ImgSpotDTO> newSpots = makeSpotDTOs(newSpotMatrix, contId); + enrichWithPermIds(newSpots, containerPermId); for (ImgSpotDTO spot : newSpots) { long id = dao.addSpot(spot); @@ -303,8 +309,35 @@ class HCSDatasetUploader return newSpots; } - private static Boolean[][] extractNewSpots(int rows, int columns, - List<AcquiredPlateImage> images, List<ImgSpotDTO> existingSpots) + private void enrichWithPermIds(List<ImgSpotDTO> newSpots, String containerPermId) + { + Map<String, String> permIds = getOrCreateWells(newSpots, containerPermId); + for (ImgSpotDTO spot : newSpots) + { + spot.setPermId(permIds.get(createCoordinate(spot))); + } + } + + private Map<String, String> getOrCreateWells(List<ImgSpotDTO> newSpots, String containerPermId) + { + IEncapsulatedOpenBISService server = ServiceProvider.getOpenBISService(); + Set<String> codes = new HashSet<String>(); + for (ImgSpotDTO spot : newSpots) + { + codes.add(createCoordinate(spot)); + } + return server.listOrRegisterComponents(containerPermId, codes, + ScreeningConstants.OLIGO_WELL_TYPE_CODE); + } + + String createCoordinate(ImgSpotDTO spot) + { + return Location.tryCreateMatrixCoordinateFromLocation(new Location(spot.getColumn(), spot + .getRow())); + } + + private static Boolean[][] extractNewSpots(int rows, int columns, List<AcquiredPlateImage> images, + List<ImgSpotDTO> existingSpots) { Boolean[][] spots = extractExistingSpots(rows, columns, images); unmarkSpots(existingSpots, spots); diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/IImagingUploadDAO.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/IImagingUploadDAO.java index 54ece75b656..430795bf0d6 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/IImagingUploadDAO.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/IImagingUploadDAO.java @@ -103,8 +103,8 @@ public interface IImagingUploadDAO extends TransactionQuery + "(?{1.filePath}, ?{1.page}, ?{1.colorComponentAsString}) returning ID") public long addImage(ImgImageDTO image); - @Select("insert into SPOTS (X, Y, CONT_ID) values " - + "(?{1.column}, ?{1.row}, ?{1.containerId}) returning ID") + @Select("insert into SPOTS (X, Y, CONT_ID, PERM_ID) values " + + "(?{1.column}, ?{1.row}, ?{1.containerId}, ?{1.permId}) returning ID") public long addSpot(ImgSpotDTO spot); // updates diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/ImgSpotDTO.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/ImgSpotDTO.java index 8815546b8ab..2927d99d3ca 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/ImgSpotDTO.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/ImgSpotDTO.java @@ -29,6 +29,9 @@ public class ImgSpotDTO extends AbstractHashable @AutoGeneratedKeys private long id; + @ResultColumn("PERM_ID") + private String permId; + // position in the container, one-based (e.g. well column) @ResultColumn("X") private Integer column; @@ -46,13 +49,24 @@ public class ImgSpotDTO extends AbstractHashable // All Data-Object classes must have a default constructor. } - public ImgSpotDTO(Integer row, Integer column, long containerId) + public ImgSpotDTO(/* String permId, */Integer row, Integer column, long containerId) { + /* this.permId = permId; */ this.column = column; this.row = row; this.containerId = containerId; } + public String getPermId() + { + return permId; + } + + public void setPermId(String permId) + { + this.permId = permId; + } + public long getId() { return id; diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/LibraryExtractor.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/LibraryExtractor.java index 1904fc6cc4f..bed76500635 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/LibraryExtractor.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/LibraryExtractor.java @@ -108,7 +108,17 @@ class LibraryExtractor .asList(new NamedInputStream(new FileInputStream(platesFile), platesFile .getName(), null)), null, null, true, BatchOperationKind.REGISTRATION); - return prepared.getSamples(); + List<NewSamplesWithTypes> samples = prepared.getSamples(); + setUpdatableTypes(samples); + return samples; + } + + private static void setUpdatableTypes(List<NewSamplesWithTypes> samples) + { + for (NewSamplesWithTypes s : samples) + { + s.setAllowUpdateIfExist(true); + } } private static List<NewMaterial> extractMaterials(File genesFile) throws FileNotFoundException diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/LibraryRegistrationTask.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/LibraryRegistrationTask.java index 98492ed33d6..fe67c6484c5 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/LibraryRegistrationTask.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/server/LibraryRegistrationTask.java @@ -90,7 +90,7 @@ class LibraryRegistrationTask implements Runnable } try { - genericServer.registerSamples(sessionToken, newSamplesWithType); + genericServer.registerOrUpdateSamples(sessionToken, newSamplesWithType); for (NewSamplesWithTypes s : newSamplesWithType) { message.append("Successfuly registered " + s.getNewSamples().size() diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ScreeningConstants.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ScreeningConstants.java index 40d8d451d4f..66969a8398f 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ScreeningConstants.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ScreeningConstants.java @@ -50,6 +50,10 @@ public class ScreeningConstants // type of the dataset which stores image analysis data, there should be at most one public static final String IMAGE_ANALYSIS_DATASET_TYPE = "HCS_IMAGE_ANALYSIS_DATA"; + public static final String OLIGO_WELL_TYPE_CODE = "OLIGO_WELL"; + + public static final String CONTROL_WELL_TYPE_CODE = "CONTROL_WELL"; + public static final String PLATE_PLUGIN_TYPE_CODE = "PLATE"; public static final String LIBRARY_PLUGIN_TYPE_CODE = "LIBRARY"; diff --git a/screening/source/sql/postgresql/001/schema-001.sql b/screening/source/sql/postgresql/001/schema-001.sql index 5385d12e09b..ddd0cc8dd89 100644 --- a/screening/source/sql/postgresql/001/schema-001.sql +++ b/screening/source/sql/postgresql/001/schema-001.sql @@ -45,6 +45,7 @@ CREATE INDEX CONTAINERS_EXPE_IDX ON CONTAINERS(EXPE_ID); CREATE TABLE SPOTS ( ID BIGSERIAL NOT NULL, + PERM_ID CODE NOT NULL, -- position in the container, one-based X INTEGER, @@ -52,6 +53,7 @@ CREATE TABLE SPOTS ( CONT_ID TECH_ID NOT NULL, PRIMARY KEY (ID), + UNIQUE (PERM_ID), CONSTRAINT FK_SPOT_1 FOREIGN KEY (CONT_ID) REFERENCES CONTAINERS (ID) ON DELETE CASCADE ON UPDATE CASCADE ); diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/ImagingUploadDAOTest.java b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/ImagingUploadDAOTest.java index 9f7992d56c9..a8eb51dcc7f 100644 --- a/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/ImagingUploadDAOTest.java +++ b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/ImagingUploadDAOTest.java @@ -39,6 +39,8 @@ import ch.systemsx.cisd.openbis.dss.etl.dataaccess.ImgImageDTO.ColorComponent; public class ImagingUploadDAOTest extends AbstractDBTest { + private static final String PERM_ID = "PERM_ID"; + private static final int PAGE = 1; private static final int Y_TILE_ROW = 2; @@ -202,6 +204,7 @@ public class ImagingUploadDAOTest extends AbstractDBTest private long addSpot(long containerId) { final ImgSpotDTO spot = new ImgSpotDTO(Y_WELL_ROW, X_WELL_COLUMN, containerId); + spot.setPermId(PERM_ID); return dao.addSpot(spot); } -- GitLab