diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DefaultEntityOperationService.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DefaultEntityOperationService.java index 9188f312dd57ce6fc80b5256537d4db943fcc83c..4a0d533f91d5a0f68655ac578e13eb13f7a34959 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DefaultEntityOperationService.java +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/DefaultEntityOperationService.java @@ -18,6 +18,7 @@ package ch.systemsx.cisd.etlserver.registrator; import java.util.ArrayList; import java.util.List; +import java.util.Map; import ch.systemsx.cisd.etlserver.ITopLevelDataSetRegistratorDelegate; import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; @@ -25,6 +26,7 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.dto.AtomicEntityOperationDeta import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation; import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetRegistrationInformation; 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.NewProject; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSpace; @@ -78,6 +80,7 @@ public class DefaultEntityOperationService<T extends DataSetInformation> impleme List<NewExperiment> experimentRegistrations = details.getExperimentRegistrations(); List<SampleUpdatesDTO> sampleUpdates = details.getSampleUpdates(); List<NewSample> sampleRegistrations = details.getSampleRegistrations(); + Map<String, List<NewMaterial>> materialRegistrations = details.getMaterialRegistrations(); List<DataSetUpdatesDTO> dataSetUpdates = details.getDataSetUpdates(); List<NewExternalData> dataSetRegistrations = new ArrayList<NewExternalData>(); @@ -89,8 +92,8 @@ public class DefaultEntityOperationService<T extends DataSetInformation> impleme return new ch.systemsx.cisd.openbis.generic.shared.dto.AtomicEntityOperationDetails( details.tryUserIdOrNull(), spaceRegistrations, projectRegistrations, - experimentRegistrations, sampleUpdates, sampleRegistrations, dataSetRegistrations, - dataSetUpdates); + experimentRegistrations, sampleUpdates, sampleRegistrations, materialRegistrations, + dataSetRegistrations, dataSetUpdates); } } \ No newline at end of file diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/IDataSetRegistrationTransaction.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/IDataSetRegistrationTransaction.java index 2ed6b074ed73db8da162ce3619e0523d9ec654ca..47118f6278933a4d4ae6bd61e74410dd04fed8ba 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/IDataSetRegistrationTransaction.java +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/IDataSetRegistrationTransaction.java @@ -129,6 +129,21 @@ public interface IDataSetRegistrationTransaction */ ISpaceImmutable getSpace(String spaceCode); + /** + * Get a material from the openBIS AS. Returns null if the space does not exist. + * + * @return A material or null + */ + IMaterialImmutable getMaterial(String materialCode, String materialType); + + /** + * Create a new space to register with the openBIS AS. + * + * @param materialCode the code of the material + * @param materialType the type of the material + */ + IMaterial createNewMaterial(String materialCode, String materialType); + // File operations -- The source and destination paths are local to the incoming data set folder // or incoming directory if the data set is just one file diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/IMaterial.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/IMaterial.java new file mode 100644 index 0000000000000000000000000000000000000000..cd3a29f038f30c6b81ea3045cc516af2c24d90ff --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/IMaterial.java @@ -0,0 +1,30 @@ +/* + * Copyright 2011 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.etlserver.registrator.api.v1; + + +/** + * @author Kaloyan Enimanev + */ +public interface IMaterial extends IMaterialImmutable +{ + /** + * Set the value for a property. + */ + void setPropertyValue(String propertyCode, String propertyValue); + +} diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/IMaterialImmutable.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/IMaterialImmutable.java new file mode 100644 index 0000000000000000000000000000000000000000..bf45c55ab901dd54560affae0266c691b941ea38 --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/IMaterialImmutable.java @@ -0,0 +1,46 @@ +/* + * Copyright 2011 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.etlserver.registrator.api.v1; + +/** + * @author Kaloyan Enimanev + */ +public interface IMaterialImmutable +{ + + /** + * Return the code for this material. + */ + String getCode(); + + /** + * Return the type for this material. May be null. + */ + String getMaterialType(); + + /** + * Return true if the material exists in the database. + */ + boolean isExistingMaterial(); + + /** + * Return the value of a property specified by a code. May return null of no such property with + * code <code>propertyCode</code> is found. + */ + String getPropertyValue(String propertyCode); + +} diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/AbstractTransactionState.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/AbstractTransactionState.java index d2fdff508001368a2243d390bb02c94ef4a1deed..6e2900d945916d5b4ca17b9de80e2e626cc54da6 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/AbstractTransactionState.java +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/AbstractTransactionState.java @@ -18,7 +18,9 @@ package ch.systemsx.cisd.etlserver.registrator.api.v1.impl; import java.io.File; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import ch.systemsx.cisd.common.exceptions.NotImplementedException; import ch.systemsx.cisd.common.filesystem.FileUtilities; @@ -32,6 +34,7 @@ import ch.systemsx.cisd.etlserver.registrator.api.v1.IDataSetImmutable; import ch.systemsx.cisd.etlserver.registrator.api.v1.IDataSetUpdatable; import ch.systemsx.cisd.etlserver.registrator.api.v1.IExperiment; import ch.systemsx.cisd.etlserver.registrator.api.v1.IExperimentImmutable; +import ch.systemsx.cisd.etlserver.registrator.api.v1.IMaterial; import ch.systemsx.cisd.etlserver.registrator.api.v1.IProject; import ch.systemsx.cisd.etlserver.registrator.api.v1.ISample; import ch.systemsx.cisd.etlserver.registrator.api.v1.ISampleImmutable; @@ -42,6 +45,7 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation; import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetRegistrationInformation; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData; 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.NewProject; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSpace; @@ -112,6 +116,8 @@ abstract class AbstractTransactionState<T extends DataSetInformation> private final List<Sample> samplesToBeUpdated = new ArrayList<Sample>(); + private final List<Material> materialsToBeRegistered = new ArrayList<Material>(); + private String userIdOrNull = null; public LiveTransactionState(DataSetRegistrationTransaction<T> parent, @@ -301,6 +307,13 @@ abstract class AbstractTransactionState<T extends DataSetInformation> return project; } + public IMaterial createNewMaterial(String materialCode, String materialType) + { + Material material = new Material(materialCode, materialType); + materialsToBeRegistered.add(material); + return material; + } + public String moveFile(String src, IDataSet dst) { File srcFile = new File(src); @@ -436,6 +449,7 @@ abstract class AbstractTransactionState<T extends DataSetInformation> List<NewExperiment> experimentRegistrations = convertExperimentsToBeRegistered(); List<SampleUpdatesDTO> sampleUpdates = convertSamplesToBeUpdated(); List<NewSample> sampleRegistrations = convertSamplesToBeRegistered(); + Map<String, List<NewMaterial>> materialRegistrations = convertMaterialsToBeRegistered(); List<DataSetUpdatesDTO> dataSetUpdates = convertDataSetsToBeUpdated(); // experiment updates not yet supported @@ -444,8 +458,8 @@ abstract class AbstractTransactionState<T extends DataSetInformation> AtomicEntityOperationDetails<T> registrationDetails = new AtomicEntityOperationDetails<T>(getUserId(), spaceRegistrations, projectRegistrations, experimentUpdates, experimentRegistrations, - sampleUpdates, sampleRegistrations, dataSetRegistrations, - dataSetUpdates); + sampleUpdates, sampleRegistrations, materialRegistrations, + dataSetRegistrations, dataSetUpdates); return registrationDetails; } @@ -509,6 +523,24 @@ abstract class AbstractTransactionState<T extends DataSetInformation> return result; } + private Map<String, List<NewMaterial>> convertMaterialsToBeRegistered() + { + Map<String, List<NewMaterial>> result = new HashMap<String, List<NewMaterial>>(); + for (Material material : materialsToBeRegistered) + { + NewMaterial converted = ConversionUtils.convertToNewMaterial(material); + String materialType = material.getMaterialType(); + List<NewMaterial> materialsOfSameType = result.get(materialType); + if (materialsOfSameType == null) + { + materialsOfSameType = new ArrayList<NewMaterial>(); + result.put(materialType, materialsOfSameType); + } + materialsOfSameType.add(converted); + } + return result; + } + @Override public boolean isCommitted() { diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/ConversionUtils.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/ConversionUtils.java index cc32cb2e3b726479b8dc4a5bea4ac9749e7726b7..0291f9158698598f4033adb25966d3a57bad1466 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/ConversionUtils.java +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/ConversionUtils.java @@ -29,6 +29,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment; 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.NewProject; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSpace; @@ -222,4 +223,13 @@ public class ConversionUtils return dataSetUpdate; } + public static NewMaterial convertToNewMaterial(Material material) + { + NewMaterial newMaterial = new NewMaterial(material.getCode()); + IEntityProperty[] properties = + material.getMaterial().getProperties().toArray(new IEntityProperty[0]); + newMaterial.setProperties(properties); + return newMaterial; + } + } diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/DataSetRegistrationTransaction.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/DataSetRegistrationTransaction.java index 1a848328041cc6ae9eed2d83f5e73eba127946ac..07adfb05f059905c4f763bb13f80a78b7d0df03c 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/DataSetRegistrationTransaction.java +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/DataSetRegistrationTransaction.java @@ -39,6 +39,8 @@ import ch.systemsx.cisd.etlserver.registrator.api.v1.IDataSetRegistrationTransac import ch.systemsx.cisd.etlserver.registrator.api.v1.IDataSetUpdatable; import ch.systemsx.cisd.etlserver.registrator.api.v1.IExperiment; import ch.systemsx.cisd.etlserver.registrator.api.v1.IExperimentImmutable; +import ch.systemsx.cisd.etlserver.registrator.api.v1.IMaterial; +import ch.systemsx.cisd.etlserver.registrator.api.v1.IMaterialImmutable; import ch.systemsx.cisd.etlserver.registrator.api.v1.IProject; import ch.systemsx.cisd.etlserver.registrator.api.v1.IProjectImmutable; import ch.systemsx.cisd.etlserver.registrator.api.v1.ISample; @@ -53,6 +55,7 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; import ch.systemsx.cisd.openbis.dss.generic.shared.dto.AtomicEntityOperationDetails; import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation; import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetRegistrationInformation; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialIdentifier; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifierFactory; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier; @@ -277,6 +280,19 @@ public class DataSetRegistrationTransaction<T extends DataSetInformation> implem return (null == spaceOrNull) ? null : new SpaceImmutable(spaceOrNull); } + public IMaterialImmutable getMaterial(String materialCode, String materialType) + { + MaterialIdentifier materialIdentifier = new MaterialIdentifier(materialCode, materialType); + ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material materialOrNull = + openBisService.tryGetMaterial(materialIdentifier); + return (null == materialOrNull) ? null : new MaterialImmutable(materialOrNull); + } + + public IMaterial createNewMaterial(String materialCode, String materialType) + { + return getStateAsLiveState().createNewMaterial(materialCode, materialType); + } + public String moveFile(String src, IDataSet dst) { return getStateAsLiveState().moveFile(src, dst); diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/Material.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/Material.java new file mode 100644 index 0000000000000000000000000000000000000000..8d583bf15ac594ad4d42416c3bf068252014e1da --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/Material.java @@ -0,0 +1,60 @@ +/* + * Copyright 2011 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.etlserver.registrator.api.v1.impl; + +import java.util.ArrayList; + +import ch.systemsx.cisd.etlserver.registrator.api.v1.IMaterial; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType; +import ch.systemsx.cisd.openbis.generic.shared.util.EntityHelper; + +/** + * @author Kaloyan Enimanev + */ +public class Material extends MaterialImmutable implements IMaterial +{ + + private static ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material buildMaterialWithCodeAndType( + String code, String type) + { + ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material material = + new ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material(); + material.setCode(code); + MaterialType materialType = new MaterialType(); + materialType.setCode(type); + material.setMaterialType(materialType); + material.setProperties(new ArrayList<IEntityProperty>()); + + return material; + } + + public Material(ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material material) + { + super(material); + } + + public Material(String code, String type) + { + super(buildMaterialWithCodeAndType(code, type), false); + } + + public void setPropertyValue(String propertyCode, String propertyValue) + { + EntityHelper.createOrUpdateProperty(getMaterial(), propertyCode, propertyValue); + } +} diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/MaterialImmutable.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/MaterialImmutable.java new file mode 100644 index 0000000000000000000000000000000000000000..f88f0657f9731cceb6fd96fe7a38dedff6e8cae2 --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/MaterialImmutable.java @@ -0,0 +1,83 @@ +/* + * Copyright 2011 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.etlserver.registrator.api.v1.impl; + +import ch.systemsx.cisd.common.exceptions.UserFailureException; +import ch.systemsx.cisd.etlserver.registrator.api.v1.IMaterialImmutable; +import ch.systemsx.cisd.openbis.generic.shared.util.EntityHelper; + +/** + * @author Kaloyan Enimanev + */ +public class MaterialImmutable implements IMaterialImmutable +{ + private final ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material material; + + private final boolean existingMaterial; + + public MaterialImmutable(ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material material) + { + this(material, true); + } + + public MaterialImmutable(ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material material, + boolean existingMaterial) + { + this.material = material; + this.existingMaterial = existingMaterial; + } + + public String getCode() + { + return material.getCode(); + } + + public String getMaterialType() + { + if (material.getMaterialType() != null) + { + return material.getMaterialType().getCode(); + } + return null; + } + + public boolean isExistingMaterial() + { + return existingMaterial; + } + + public ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material getMaterial() + { + return material; + } + + /** + * Throw an exception if the sample does not exist + */ + protected void checkExists() + { + if (false == isExistingMaterial()) + { + throw new UserFailureException("Material does not exist."); + } + } + + public String getPropertyValue(String propertyCode) + { + return EntityHelper.tryFindPropertyValue(material, propertyCode); + } +} 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 9ae22fd6dd4f77d48c9b8efc29eac3f187ca2e6f..12b0f51c7629df86563e2ab325fef9afc4b639e6 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 @@ -47,6 +47,8 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentType; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListSampleCriteria; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialIdentifier; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewExperiment; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSamplesWithTypes; @@ -558,4 +560,9 @@ public final class EncapsulatedOpenBISService implements IEncapsulatedOpenBISSer return service.listExperiments(session.getToken(), projectIdentifier); } + public Material tryGetMaterial(MaterialIdentifier materialIdentifier) + { + return service.tryGetMaterial(session.getToken(), materialIdentifier); + } + } \ 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 2867468414ac7c2ba43647d01300148835dddf92..9140450f3a68a1a3b845362997b5a9185081fd86 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 @@ -34,6 +34,8 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentType; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListSampleCriteria; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialIdentifier; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewExperiment; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSamplesWithTypes; @@ -153,6 +155,12 @@ public interface IEncapsulatedOpenBISService public SampleIdentifier tryToGetSampleIdentifier(String samplePermID) throws UserFailureException; + /** + * For given {@link MaterialIdentifier} returns the corresponding {@link Material}. + */ + @ManagedAuthentication + public Material tryGetMaterial(MaterialIdentifier materialIdentifier); + /** * Lists vocabulary terms. */ diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/dto/AtomicEntityOperationDetails.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/dto/AtomicEntityOperationDetails.java index 218a7ae9dc7dbebad8d4a307acc779b1917f31ba..78b7cea0d1a23767dcabd6e6d57bde141f5c77cf 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/dto/AtomicEntityOperationDetails.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/dto/AtomicEntityOperationDetails.java @@ -18,9 +18,12 @@ package ch.systemsx.cisd.openbis.dss.generic.shared.dto; import java.io.Serializable; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; 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.NewProject; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSpace; @@ -53,6 +56,8 @@ public class AtomicEntityOperationDetails<T extends DataSetInformation> implemen private final List<NewSample> sampleRegistrations; + private final Map<String /* material type */, List<NewMaterial>> materialRegistrations; + private final List<DataSetRegistrationInformation<T>> dataSetRegistrations; private final List<DataSetUpdatesDTO> dataSetUpdates; @@ -62,6 +67,7 @@ public class AtomicEntityOperationDetails<T extends DataSetInformation> implemen List<ExperimentUpdatesDTO> experimentUpdates, List<NewExperiment> experimentRegistrations, List<SampleUpdatesDTO> sampleUpdates, List<NewSample> sampleRegistrations, + Map<String, List<NewMaterial>> materialRegistrations, List<DataSetRegistrationInformation<T>> dataSetRegistrations, List<DataSetUpdatesDTO> dataSetUpdates) { @@ -72,6 +78,7 @@ public class AtomicEntityOperationDetails<T extends DataSetInformation> implemen this.experimentRegistrations = new ArrayList<NewExperiment>(experimentRegistrations); this.sampleUpdates = new ArrayList<SampleUpdatesDTO>(sampleUpdates); this.sampleRegistrations = new ArrayList<NewSample>(sampleRegistrations); + this.materialRegistrations = new HashMap<String, List<NewMaterial>>(materialRegistrations); this.dataSetRegistrations = new ArrayList<DataSetRegistrationInformation<T>>(dataSetRegistrations); this.dataSetUpdates = new ArrayList<DataSetUpdatesDTO>(dataSetUpdates); @@ -122,4 +129,9 @@ public class AtomicEntityOperationDetails<T extends DataSetInformation> implemen return projectRegistrations; } + public Map<String, List<NewMaterial>> getMaterialRegistrations() + { + return materialRegistrations; + } + } diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISServiceTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISServiceTest.java index 6d86c4aaccf6dfa79a31634cfbdf63d5a612bb36..e6dd35f7bcb25df2ea400af133c3669cdc981037 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISServiceTest.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISServiceTest.java @@ -17,7 +17,9 @@ package ch.systemsx.cisd.openbis.dss.generic.server; import java.util.Arrays; +import java.util.Collections; import java.util.Date; +import java.util.List; import org.jmock.Expectations; import org.jmock.Mockery; @@ -33,6 +35,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment; 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.NewProject; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSpace; @@ -161,6 +164,7 @@ public class EncapsulatedOpenBISServiceTest new AtomicEntityOperationDetails(null, Arrays.<NewSpace> asList(), Arrays.<NewProject> asList(), Arrays.<NewExperiment> asList(), Arrays.<SampleUpdatesDTO> asList(), Arrays.<NewSample> asList(), + Collections.<String, List<NewMaterial>> emptyMap(), Arrays.asList(data), Arrays.<DataSetUpdatesDTO> asList()); context.checking(new Expectations() { 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 9770d87d735b6fc15b8dc8720cd03166d806a9d1..b8a7dd7ae129e1d7ddd0a0b81ea64f5a1d1a5eb5 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 @@ -23,6 +23,8 @@ import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import ch.systemsx.cisd.authentication.IAuthenticationService; @@ -39,6 +41,7 @@ import ch.systemsx.cisd.openbis.generic.server.business.bo.IDataBO; import ch.systemsx.cisd.openbis.generic.server.business.bo.IExperimentBO; import ch.systemsx.cisd.openbis.generic.server.business.bo.IExperimentTable; import ch.systemsx.cisd.openbis.generic.server.business.bo.IGroupBO; +import ch.systemsx.cisd.openbis.generic.server.business.bo.IMaterialBO; import ch.systemsx.cisd.openbis.generic.server.business.bo.IProjectBO; import ch.systemsx.cisd.openbis.generic.server.business.bo.IRoleAssignmentTable; import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleBO; @@ -76,7 +79,10 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Grantee; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListOrSearchSampleCriteria; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListSampleCriteria; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialIdentifier; 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.NewProject; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSamplesWithTypes; @@ -143,6 +149,7 @@ import ch.systemsx.cisd.openbis.generic.shared.translator.ExperimentTranslator; import ch.systemsx.cisd.openbis.generic.shared.translator.ExperimentTranslator.LoadableFields; import ch.systemsx.cisd.openbis.generic.shared.translator.ExperimentTypeTranslator; import ch.systemsx.cisd.openbis.generic.shared.translator.GroupTranslator; +import ch.systemsx.cisd.openbis.generic.shared.translator.MaterialTranslator; import ch.systemsx.cisd.openbis.generic.shared.translator.PersonTranslator; import ch.systemsx.cisd.openbis.generic.shared.translator.ProjectTranslator; import ch.systemsx.cisd.openbis.generic.shared.translator.SampleTranslator; @@ -1070,7 +1077,6 @@ public class ETLService extends AbstractCommonServer<IETLService> implements IET // space does not exist return null; } - } public Project tryGetProject(String sessionToken, ProjectIdentifier projectIdentifier) @@ -1089,6 +1095,21 @@ public class ETLService extends AbstractCommonServer<IETLService> implements IET } } + public Material tryGetMaterial(String sessionToken, MaterialIdentifier materialIdentifier) + { + final Session session = getSession(sessionToken); + final IMaterialBO bo = businessObjectFactory.createMaterialBO(session); + try + { + bo.loadByMaterialIdentifier(materialIdentifier); + return MaterialTranslator.translate(bo.getMaterial()); + } catch (UserFailureException ufe) + { + // material does not exist + return null; + } + } + public AtomicEntityOperationResult performEntityOperations(String sessionToken, AtomicEntityOperationDetails operationDetails) { @@ -1096,6 +1117,8 @@ public class ETLService extends AbstractCommonServer<IETLService> implements IET List<Space> spacesCreated = createSpaces(session, operationDetails); + List<Material> materialsCreated = createMaterials(session, operationDetails); + List<Project> projectsCreated = createProjects(session, operationDetails); List<Experiment> experimentsCreated = createExperiments(session, operationDetails); @@ -1109,7 +1132,7 @@ public class ETLService extends AbstractCommonServer<IETLService> implements IET List<ExternalData> dataSetsUpdated = updateDataSets(session, operationDetails); return new AtomicEntityOperationResult(spacesCreated, projectsCreated, experimentsCreated, - samplesUpdated, samplesCreated, dataSetsCreated, dataSetsUpdated); + samplesUpdated, samplesCreated, materialsCreated, dataSetsCreated, dataSetsUpdated); } private List<Space> createSpaces(Session session, AtomicEntityOperationDetails operationDetails) @@ -1125,6 +1148,24 @@ public class ETLService extends AbstractCommonServer<IETLService> implements IET return GroupTranslator.translate(spacePEsCreated); } + private List<Material> createMaterials(Session session, + AtomicEntityOperationDetails operationDetails) + { + MaterialHelper materialHelper = + new MaterialHelper(session, businessObjectFactory, getDAOFactory(), + getPropertiesBatchManager()); + Map<String, List<NewMaterial>> materialRegs = operationDetails.getMaterialRegistrations(); + List<Material> registeredMaterials = new ArrayList<Material>(); + for (Entry<String, List<NewMaterial>> newMaterialsEntry : materialRegs.entrySet()) + { + String materialType = newMaterialsEntry.getKey(); + List<NewMaterial> newMaterials = newMaterialsEntry.getValue(); + List<Material> materials = materialHelper.registerMaterials(materialType, newMaterials); + registeredMaterials.addAll(materials); + } + return registeredMaterials; + } + private SpacePE registerSpaceInternal(Session session, NewSpace newSpace, String registratorUserIdOrNull) { 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 cb7bac3b0826cacfd46f2055946e507c286c4be6..83c305668bdb2a07417fffd2c3c1b3ef2ce4eecd 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 @@ -36,6 +36,8 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentType; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListSampleCriteria; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialIdentifier; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewExperiment; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSamplesWithTypes; @@ -487,4 +489,10 @@ public class ETLServiceLogger extends AbstractServerLogger implements IETLServic logAccess(sessionToken, "searchForDataSets", "%s", searchCriteria); return null; } + + public Material tryGetMaterial(String sessionToken, MaterialIdentifier materialIdentifier) + { + logAccess(sessionToken, "tryGetMaterial", "%s", materialIdentifier); + return null; + } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/MaterialHelper.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/MaterialHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..7db559088f0bac20950861eddff5714bda6eb1a1 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/MaterialHelper.java @@ -0,0 +1,273 @@ +/* + * Copyright 2011 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.openbis.generic.server; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.log4j.Logger; + +import ch.systemsx.cisd.common.exceptions.UserFailureException; +import ch.systemsx.cisd.common.logging.LogCategory; +import ch.systemsx.cisd.common.logging.LogFactory; +import ch.systemsx.cisd.openbis.generic.server.batch.BatchOperationExecutor; +import ch.systemsx.cisd.openbis.generic.server.batch.IBatchOperation; +import ch.systemsx.cisd.openbis.generic.server.business.IPropertiesBatchManager; +import ch.systemsx.cisd.openbis.generic.server.business.bo.IAbstractBussinessObjectFactory; +import ch.systemsx.cisd.openbis.generic.server.business.bo.IMaterialTable; +import ch.systemsx.cisd.openbis.generic.server.business.bo.MaterialUpdateDTO; +import ch.systemsx.cisd.openbis.generic.server.business.bo.materiallister.IMaterialLister; +import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory; +import ch.systemsx.cisd.openbis.generic.shared.basic.CodeConverter; +import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListMaterialCriteria; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewMaterial; +import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePE; +import ch.systemsx.cisd.openbis.generic.shared.dto.MaterialPE; +import ch.systemsx.cisd.openbis.generic.shared.dto.MaterialTypePE; +import ch.systemsx.cisd.openbis.generic.shared.dto.Session; +import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind; +import ch.systemsx.cisd.openbis.generic.shared.translator.MaterialTranslator; +import ch.systemsx.cisd.openbis.generic.shared.translator.MaterialTypeTranslator; +import ch.systemsx.cisd.openbis.generic.shared.util.ServerUtils; + +/** + * @author Kaloyan Enimanev + */ +public class MaterialHelper +{ + + private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, + MaterialHelper.class); + + private final Session session; + + private final IAbstractBussinessObjectFactory businessObjectFactory; + + private final IDAOFactory daoFactory; + + private final IPropertiesBatchManager propertiesBatchManager; + + public MaterialHelper(Session session, + IAbstractBussinessObjectFactory businessObjectFactory, IDAOFactory daoFactory, + IPropertiesBatchManager propertiesBatchManager) + { + this.session = session; + this.businessObjectFactory = businessObjectFactory; + this.daoFactory = daoFactory; + this.propertiesBatchManager = propertiesBatchManager; + } + + public List<Material> registerMaterials(String materialTypeCode, + final List<NewMaterial> newMaterials) + { + assert materialTypeCode != null : "Unspecified material type."; + assert newMaterials != null : "Unspecified new materials."; + + // Does nothing if material list is empty. + if (newMaterials.size() == 0) + { + return Collections.emptyList(); + } + ServerUtils.prevalidate(newMaterials, "material"); + final MaterialTypePE materialTypePE = findMaterialType(materialTypeCode); + final List<MaterialPE> registeredMaterials = new ArrayList<MaterialPE>(); + propertiesBatchManager.manageProperties(materialTypePE, newMaterials, + session.tryGetPerson()); + IBatchOperation<NewMaterial> strategy = new IBatchOperation<NewMaterial>() + { + + public void execute(List<NewMaterial> entities) + { + final IMaterialTable materialTable = + businessObjectFactory.createMaterialTable(session); + materialTable.add(entities, materialTypePE); + materialTable.save(); + registeredMaterials.addAll(materialTable.getMaterials()); + } + + public List<NewMaterial> getAllEntities() + { + return newMaterials; + } + + public String getEntityName() + { + return "material"; + } + + public String getOperationName() + { + return "register"; + } + }; + BatchOperationExecutor.executeInBatches(strategy); + + return MaterialTranslator.translate(registeredMaterials); + } + + public int updateMaterials(String materialTypeCode, + final List<NewMaterial> newMaterials, final boolean ignoreUnregisteredMaterials) + throws UserFailureException + { + assert materialTypeCode != null : "Unspecified material type."; + assert newMaterials != null : "Unspecified new materials."; + + // Does nothing if material list is empty. + if (newMaterials.size() == 0) + { + return 0; + } + + ServerUtils.prevalidate(newMaterials, "material"); + + final AtomicInteger count = new AtomicInteger(0); + final Map<String/* code */, Material> existingMaterials = listMaterials(materialTypeCode); + + final MaterialTypePE materialTypePE = findMaterialType(materialTypeCode); + propertiesBatchManager.manageProperties(materialTypePE, newMaterials, + session.tryGetPerson()); + IBatchOperation<NewMaterial> strategy = new IBatchOperation<NewMaterial>() + { + public void execute(List<NewMaterial> entities) + { + List<MaterialUpdateDTO> materialUpdates = new ArrayList<MaterialUpdateDTO>(); + for (NewMaterial material : entities) + { + Material existingMaterial = + existingMaterials.get(CodeConverter.tryToDatabase(material + .getCode())); + if (existingMaterial != null) + { + materialUpdates.add(createMaterialUpdate(existingMaterial, material)); + count.incrementAndGet(); + } else if (ignoreUnregisteredMaterials == false) + { + throw new UserFailureException("Can not update unregistered material '" + + material.getCode() + + "'. Please use checkbox for ignoring unregistered materials."); + } + } + updateMaterials(materialUpdates); + } + + public List<NewMaterial> getAllEntities() + { + return newMaterials; + } + + public String getEntityName() + { + return "material"; + } + + public String getOperationName() + { + return "update"; + } + }; + BatchOperationExecutor.executeInBatches(strategy); + return count.get(); + } + + public void registerOrUpdateMaterials(String materialTypeCode, List<NewMaterial> materials) + { + Map<String/* code */, Material> existingMaterials = listMaterials(materialTypeCode); + List<NewMaterial> materialsToRegister = new ArrayList<NewMaterial>(); + List<MaterialUpdateDTO> materialUpdates = new ArrayList<MaterialUpdateDTO>(); + for (NewMaterial material : materials) + { + Material existingMaterial = + existingMaterials.get(CodeConverter.tryToDatabase(material.getCode())); + if (existingMaterial != null) + { + materialUpdates.add(createMaterialUpdate(existingMaterial, material)); + } else + { + materialsToRegister.add(material); + } + } + registerMaterials(materialTypeCode, materialsToRegister); + updateMaterials(materialUpdates); + operationLog.info(String.format("Number of newly registered materials: %d, " + + "number of existing materials which have been updated: %d", + materialsToRegister.size(), materialUpdates.size())); + + } + + private static MaterialUpdateDTO createMaterialUpdate(Material existingMaterial, + NewMaterial material) + { + return new MaterialUpdateDTO(new TechId(existingMaterial.getId()), Arrays.asList(material + .getProperties()), existingMaterial.getModificationDate()); + } + + private void updateMaterials(List<MaterialUpdateDTO> updates) + { + if (updates.isEmpty()) + { + return; + } + IMaterialTable materialTable = businessObjectFactory.createMaterialTable(session); + materialTable.update(updates); + materialTable.save(); + } + + private Map<String/* code */, Material> listMaterials(String materialTypeCode) + { + EntityTypePE entityTypePE = + daoFactory.getEntityTypeDAO(EntityKind.MATERIAL).tryToFindEntityTypeByCode( + materialTypeCode); + MaterialType materialType = MaterialTypeTranslator.translateSimple(entityTypePE); + + IMaterialLister materialLister = businessObjectFactory.createMaterialLister(session); + ListMaterialCriteria listByTypeCriteria = new ListMaterialCriteria(materialType); + List<Material> materials = materialLister.list(listByTypeCriteria, false); + return asCodeToMaterialMap(materials); + } + + private static Map<String, Material> asCodeToMaterialMap(List<Material> materials) + { + Map<String, Material> map = new HashMap<String, Material>(); + for (Material material : materials) + { + map.put(material.getCode(), material); + } + return map; + } + + private MaterialTypePE findMaterialType(String materialTypeCode) + { + final MaterialTypePE materialTypePE = + (MaterialTypePE) daoFactory.getEntityTypeDAO(EntityKind.MATERIAL) + .tryToFindEntityTypeByCode(materialTypeCode); + if (materialTypePE == null) + { + throw UserFailureException.fromTemplate("Material type with code '%s' does not exist.", + materialTypeCode); + } + return materialTypePE; + } + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IAbstractBussinessObjectFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IAbstractBussinessObjectFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..7eb0f58ccdfc9297569db42aa6cde49dab1e379c --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IAbstractBussinessObjectFactory.java @@ -0,0 +1,35 @@ +/* + * Copyright 2011 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.openbis.generic.server.business.bo; + +import ch.systemsx.cisd.openbis.generic.server.business.bo.materiallister.IMaterialLister; +import ch.systemsx.cisd.openbis.generic.shared.dto.Session; + +/** + * An abstract bussiness object factory. + * + * @author Kaloyan Enimanev + */ +public interface IAbstractBussinessObjectFactory +{ + public IMaterialTable createMaterialTable(Session session); + + public IMaterialBO createMaterialBO(Session session); + + public IMaterialLister createMaterialLister(Session session); + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ICommonBusinessObjectFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ICommonBusinessObjectFactory.java index dc1a3b9ee4c243cf7c85bd300c52b08903b44e7c..a7478f32797ebb20de88230068ed7854c70835dc 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ICommonBusinessObjectFactory.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ICommonBusinessObjectFactory.java @@ -17,7 +17,6 @@ package ch.systemsx.cisd.openbis.generic.server.business.bo; import ch.systemsx.cisd.openbis.generic.server.business.bo.datasetlister.IDatasetLister; -import ch.systemsx.cisd.openbis.generic.server.business.bo.materiallister.IMaterialLister; import ch.systemsx.cisd.openbis.generic.server.business.bo.samplelister.ISampleLister; import ch.systemsx.cisd.openbis.generic.shared.dto.Session; import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind; @@ -28,7 +27,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind; * * @author Tomasz Pylak */ -public interface ICommonBusinessObjectFactory +public interface ICommonBusinessObjectFactory extends IAbstractBussinessObjectFactory { public IAttachmentBO createAttachmentBO(final Session session); @@ -63,12 +62,8 @@ public interface ICommonBusinessObjectFactory public IProjectBO createProjectBO(final Session session); - public IMaterialTable createMaterialTable(Session session); - public IEntityTypeBO createEntityTypeBO(Session session); - public IMaterialBO createMaterialBO(Session session); - public IAuthorizationGroupBO createAuthorizationGroupBO(Session session); public IGridCustomFilterOrColumnBO createGridCustomFilterBO(final Session session); @@ -78,10 +73,8 @@ public interface ICommonBusinessObjectFactory public IInvalidationBO createInvalidationBO(final Session session); // Fast listing operations - public ISampleLister createSampleLister(Session session); public IDatasetLister createDatasetLister(Session session); - public IMaterialLister createMaterialLister(Session session); } 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 2d773460d3d1eaf935f1f4cf6c5f9ab6e9fa988e..cc540753cfed2db318a3aaf23c37eb72510146fa 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 @@ -57,6 +57,8 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentType; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListSampleCriteria; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialIdentifier; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewExperiment; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSamplesWithTypes; @@ -120,20 +122,11 @@ public interface IETLLIMSService extends IServer, ISessionProvider throws UserFailureException; /** - * Gets a sample with the specified identifier. Sample is enriched with properties and the - * experiment with properties. - * - * @param sessionToken the user authentication token. Must not be <code>null</code>. - * @param sampleIdentifier an identifier which uniquely identifies the sample. - * @return <code>null</code> if no sample attached to an experiment could be found for given - * <var>sampleIdentifier</var>. + * For given {@link MaterialIdentifier} returns the corresponding {@link Material}. */ @Transactional(readOnly = true) @RolesAllowed(RoleWithHierarchy.SPACE_ETL_SERVER) - public Sample tryGetSampleWithExperiment( - final String sessionToken, - @AuthorizationGuard(guardClass = ExistingSampleOwnerIdentifierPredicate.class) final SampleIdentifier sampleIdentifier) - throws UserFailureException; + public Material tryGetMaterial(String sessionToken, MaterialIdentifier materialIdentifier); /** * Tries to get the identifier of sample with specified permanent ID. @@ -154,6 +147,22 @@ public interface IETLLIMSService extends IServer, ISessionProvider public ExperimentType getExperimentType(String sessionToken, String experimentTypeCode) throws UserFailureException; + /** + * Gets a sample with the specified identifier. Sample is enriched with properties and the + * experiment with properties. + * + * @param sessionToken the user authentication token. Must not be <code>null</code>. + * @param sampleIdentifier an identifier which uniquely identifies the sample. + * @return <code>null</code> if no sample attached to an experiment could be found for given + * <var>sampleIdentifier</var>. + */ + @Transactional(readOnly = true) + @RolesAllowed(RoleWithHierarchy.SPACE_ETL_SERVER) + public Sample tryGetSampleWithExperiment( + final String sessionToken, + @AuthorizationGuard(guardClass = ExistingSampleOwnerIdentifierPredicate.class) final SampleIdentifier sampleIdentifier) + throws UserFailureException; + /** * Returns a list of terms belonging to given vocabulary. */ diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/AtomicEntityOperationDetails.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/AtomicEntityOperationDetails.java index ab5f5ede932a0ef5b554b39d92b46005144835ac..e768b2523da4f594a409faf75e18ed5db19f4c25 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/AtomicEntityOperationDetails.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/AtomicEntityOperationDetails.java @@ -19,11 +19,14 @@ package ch.systemsx.cisd.openbis.generic.shared.dto; import java.io.Serializable; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.TreeMap; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; 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.NewProject; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSpace; @@ -55,6 +58,8 @@ public class AtomicEntityOperationDetails implements Serializable private final List<NewSample> sampleRegistrations; + private final Map<String /* material type */, List<NewMaterial>> materialRegistrations; + private final List<? extends NewExternalData> dataSetRegistrations; private final List<DataSetUpdatesDTO> dataSetUpdates; @@ -62,6 +67,7 @@ public class AtomicEntityOperationDetails implements Serializable public AtomicEntityOperationDetails(String userIdOrNull, List<NewSpace> spaceRegistrations, List<NewProject> projectRegistrations, List<NewExperiment> experimentRegistrations, List<SampleUpdatesDTO> sampleUpdates, List<NewSample> sampleRegistrations, + Map<String, List<NewMaterial>> materialRegistrations, List<? extends NewExternalData> dataSetRegistrations, List<DataSetUpdatesDTO> dataSetUpdates) { @@ -72,6 +78,7 @@ public class AtomicEntityOperationDetails implements Serializable this.experimentRegistrations = new ArrayList<NewExperiment>(experimentRegistrations); this.sampleUpdates = new ArrayList<SampleUpdatesDTO>(sampleUpdates); this.sampleRegistrations = new ArrayList<NewSample>(sampleRegistrations); + this.materialRegistrations = new TreeMap<String, List<NewMaterial>>(materialRegistrations); this.dataSetRegistrations = new ArrayList<NewExternalData>(dataSetRegistrations); this.dataSetUpdates = new ArrayList<DataSetUpdatesDTO>(dataSetUpdates); } @@ -121,6 +128,11 @@ public class AtomicEntityOperationDetails implements Serializable return projectRegistrations; } + public Map<String, List<NewMaterial>> getMaterialRegistrations() + { + return materialRegistrations; + } + @Override public String toString() { @@ -132,8 +144,10 @@ public class AtomicEntityOperationDetails implements Serializable sb.append("experimentRegistrations", experimentRegistrations); sb.append("sampleUpdates", sampleUpdates); sb.append("sampleRegistrations", sampleRegistrations); + sb.append("materialRegistrations", materialRegistrations); sb.append("dataSetRegistrations", dataSetRegistrations); sb.append("dataSetUpdates", dataSetUpdates); return sb.toString(); } + } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/AtomicEntityOperationResult.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/AtomicEntityOperationResult.java index 1e7bf47897ec11a350db9853d6d76e6507979251..a085e4e32dc0ce43f09acac201ab95df07be5a62 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/AtomicEntityOperationResult.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/AtomicEntityOperationResult.java @@ -23,6 +23,7 @@ import java.util.List; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space; @@ -48,6 +49,8 @@ public class AtomicEntityOperationResult implements Serializable private final ArrayList<Sample> samplesCreated; + private final ArrayList<Material> materialsCreated; + private final ArrayList<ExternalData> dataSetsCreated; private final ArrayList<ExternalData> dataSetsUpdated; @@ -56,13 +59,15 @@ public class AtomicEntityOperationResult implements Serializable { this(Collections.<Space> emptyList(), Collections.<Project> emptyList(), Collections.<Experiment> emptyList(), Collections.<Sample> emptyList(), Collections - .<Sample> emptyList(), Collections.<ExternalData> emptyList(), Collections + .<Sample> emptyList(), Collections.<Material> emptyList(), Collections + .<ExternalData> emptyList(), Collections .<ExternalData> emptyList()); } public AtomicEntityOperationResult(List<Space> spacesCreated, List<Project> projectsCreated, List<Experiment> experimentsCreated, List<Sample> samplesUpdated, - List<Sample> samplesCreated, List<ExternalData> dataSetsCreated, + List<Sample> samplesCreated, List<Material> materialsCreated, + List<ExternalData> dataSetsCreated, List<ExternalData> dataSetsUpdated) { this.spacesCreated = new ArrayList<Space>(spacesCreated); @@ -71,6 +76,7 @@ public class AtomicEntityOperationResult implements Serializable this.experimentsCreated = new ArrayList<Experiment>(experimentsCreated); this.samplesUpdated = new ArrayList<Sample>(samplesUpdated); this.samplesCreated = new ArrayList<Sample>(samplesCreated); + this.materialsCreated = new ArrayList<Material>(materialsCreated); this.dataSetsCreated = new ArrayList<ExternalData>(dataSetsCreated); this.dataSetsUpdated = new ArrayList<ExternalData>(dataSetsUpdated); } @@ -115,4 +121,9 @@ public class AtomicEntityOperationResult implements Serializable return projectsCreated; } + public ArrayList<Material> getMaterialsCreated() + { + return materialsCreated; + } + } 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 795344517a44a131a57a6e2563c1201a7409aecb..9ecaefa2c610ef1560dd2e4d74eb61720240c00c 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 @@ -28,6 +28,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.materiallister.IMaterialLister; +import ch.systemsx.cisd.openbis.generic.server.business.bo.materiallister.MaterialLister; 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; @@ -102,4 +104,10 @@ public final class GenericBusinessObjectFactory extends AbstractPluginBusinessOb { return SampleLister.create(getDaoFactory(), session.getBaseIndexURL()); } + + public IMaterialLister createMaterialLister(Session session) + { + return MaterialLister.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 4ed12dc99451035e36bb0e40d1d756f1998caa63..cba34dec4617bf495a3b47da52b63520bfe8c180 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 @@ -20,38 +20,31 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Date; -import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; import javax.annotation.Resource; -import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import ch.rinn.restrictions.Private; import ch.systemsx.cisd.authentication.ISessionManager; import ch.systemsx.cisd.common.exceptions.UserFailureException; -import ch.systemsx.cisd.common.logging.LogCategory; -import ch.systemsx.cisd.common.logging.LogFactory; import ch.systemsx.cisd.common.spring.IInvocationLoggerContext; import ch.systemsx.cisd.openbis.generic.server.AbstractServer; +import ch.systemsx.cisd.openbis.generic.server.MaterialHelper; import ch.systemsx.cisd.openbis.generic.server.batch.BatchOperationExecutor; import ch.systemsx.cisd.openbis.generic.server.batch.IBatchOperation; import ch.systemsx.cisd.openbis.generic.server.business.IPropertiesBatchManager; import ch.systemsx.cisd.openbis.generic.server.business.bo.IExperimentBO; -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.MaterialUpdateDTO; import ch.systemsx.cisd.openbis.generic.server.business.bo.samplelister.ISampleLister; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory; import ch.systemsx.cisd.openbis.generic.server.plugin.IDataSetTypeSlaveServerPlugin; import ch.systemsx.cisd.openbis.generic.server.plugin.ISampleTypeSlaveServerPlugin; import ch.systemsx.cisd.openbis.generic.shared.ICommonServer; -import ch.systemsx.cisd.openbis.generic.shared.basic.CodeConverter; import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AttachmentWithContent; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Code; @@ -60,10 +53,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentUpdateResult; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty; -import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListMaterialCriteria; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListOrSearchSampleCriteria; -import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material; -import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewBasicExperiment; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewDataSet; @@ -83,12 +73,10 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.UpdatedExperimentsWithT import ch.systemsx.cisd.openbis.generic.shared.basic.dto.UpdatedSample; import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetTypePE; import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetUpdatesDTO; -import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentBatchUpdatesDTO; import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentTypePE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentUpdatesDTO; -import ch.systemsx.cisd.openbis.generic.shared.dto.MaterialTypePE; import ch.systemsx.cisd.openbis.generic.shared.dto.SampleBatchUpdatesDTO; import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE; import ch.systemsx.cisd.openbis.generic.shared.dto.SampleTypePE; @@ -105,7 +93,6 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFa import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind; import ch.systemsx.cisd.openbis.generic.shared.translator.AttachmentTranslator; import ch.systemsx.cisd.openbis.generic.shared.translator.ExperimentTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.MaterialTypeTranslator; import ch.systemsx.cisd.openbis.generic.shared.translator.SampleTranslator; import ch.systemsx.cisd.openbis.generic.shared.util.ServerUtils; import ch.systemsx.cisd.openbis.plugin.generic.shared.IGenericServer; @@ -120,9 +107,6 @@ import ch.systemsx.cisd.openbis.plugin.generic.shared.ResourceNames; public final class GenericServer extends AbstractServer<IGenericServer> implements ch.systemsx.cisd.openbis.plugin.generic.shared.IGenericServer { - private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, - GenericServer.class); - @Resource(name = ResourceNames.GENERIC_BUSINESS_OBJECT_FACTORY) private IGenericBusinessObjectFactory businessObjectFactory; @@ -516,46 +500,9 @@ public final class GenericServer extends AbstractServer<IGenericServer> implemen final List<NewMaterial> newMaterials) { assert sessionToken != null : "Unspecified session token."; - assert materialTypeCode != null : "Unspecified material type."; - assert newMaterials != null : "Unspecified new materials."; + Session session = getSession(sessionToken); + getMaterialHelper(session).registerMaterials(materialTypeCode, newMaterials); - // Does nothing if material list is empty. - if (newMaterials.size() == 0) - { - return; - } - ServerUtils.prevalidate(newMaterials, "material"); - final Session session = getSession(sessionToken); - final MaterialTypePE materialTypePE = findMaterialType(materialTypeCode); - getPropertiesBatchManager().manageProperties(materialTypePE, newMaterials, - session.tryGetPerson()); - IBatchOperation<NewMaterial> strategy = new IBatchOperation<NewMaterial>() - { - - public void execute(List<NewMaterial> entities) - { - final IMaterialTable materialTable = - businessObjectFactory.createMaterialTable(session); - materialTable.add(entities, materialTypePE); - materialTable.save(); - } - - public List<NewMaterial> getAllEntities() - { - return newMaterials; - } - - public String getEntityName() - { - return "material"; - } - - public String getOperationName() - { - return "register"; - } - }; - BatchOperationExecutor.executeInBatches(strategy); } public int updateMaterials(String sessionToken, String materialTypeCode, @@ -563,81 +510,9 @@ public final class GenericServer extends AbstractServer<IGenericServer> implemen throws UserFailureException { assert sessionToken != null : "Unspecified session token."; - assert materialTypeCode != null : "Unspecified material type."; - assert newMaterials != null : "Unspecified new materials."; - - // Does nothing if material list is empty. - if (newMaterials.size() == 0) - { - return 0; - } - class Counter - { - int count; - } - final Counter counter = new Counter(); - ServerUtils.prevalidate(newMaterials, "material"); - final Map<String/* code */, Material> existingMaterials = - listMaterials(sessionToken, materialTypeCode); - final Session session = getSession(sessionToken); - - final MaterialTypePE materialTypePE = findMaterialType(materialTypeCode); - getPropertiesBatchManager().manageProperties(materialTypePE, newMaterials, - session.tryGetPerson()); - IBatchOperation<NewMaterial> strategy = new IBatchOperation<NewMaterial>() - { - public void execute(List<NewMaterial> entities) - { - List<MaterialUpdateDTO> materialUpdates = new ArrayList<MaterialUpdateDTO>(); - for (NewMaterial material : entities) - { - Material existingMaterial = - existingMaterials.get(CodeConverter.tryToDatabase(material - .getCode())); - if (existingMaterial != null) - { - materialUpdates.add(createMaterialUpdate(existingMaterial, material)); - counter.count++; - } else if (ignoreUnregisteredMaterials == false) - { - throw new UserFailureException("Can not update unregistered material '" - + material.getCode() - + "'. Please use checkbox for ignoring unregistered materials."); - } - } - updateMaterials(session.getSessionToken(), materialUpdates); - } - - public List<NewMaterial> getAllEntities() - { - return newMaterials; - } - - public String getEntityName() - { - return "material"; - } - - public String getOperationName() - { - return "update"; - } - }; - BatchOperationExecutor.executeInBatches(strategy); - return counter.count; - } - - private MaterialTypePE findMaterialType(String materialTypeCode) - { - final MaterialTypePE materialTypePE = - (MaterialTypePE) getDAOFactory().getEntityTypeDAO(EntityKind.MATERIAL) - .tryToFindEntityTypeByCode(materialTypeCode); - if (materialTypePE == null) - { - throw UserFailureException.fromTemplate("Material type with code '%s' does not exist.", - materialTypeCode); - } - return materialTypePE; + Session session = getSession(sessionToken); + return getMaterialHelper(session).updateMaterials(materialTypeCode, newMaterials, + ignoreUnregisteredMaterials); } public AttachmentWithContent getProjectFileAttachment(String sessionToken, TechId projectId, @@ -707,71 +582,9 @@ public final class GenericServer extends AbstractServer<IGenericServer> implemen public void registerOrUpdateMaterials(String sessionToken, String materialTypeCode, List<NewMaterial> materials) { - Map<String/* code */, Material> existingMaterials = - listMaterials(sessionToken, materialTypeCode); - List<NewMaterial> materialsToRegister = new ArrayList<NewMaterial>(); - List<MaterialUpdateDTO> materialUpdates = new ArrayList<MaterialUpdateDTO>(); - for (NewMaterial material : materials) - { - Material existingMaterial = - existingMaterials.get(CodeConverter.tryToDatabase(material.getCode())); - if (existingMaterial != null) - { - materialUpdates.add(createMaterialUpdate(existingMaterial, material)); - } else - { - materialsToRegister.add(material); - } - } - registerMaterials(sessionToken, materialTypeCode, materialsToRegister); - updateMaterials(sessionToken, materialUpdates); - operationLog.info(String.format("Number of newly registered materials: %d, " - + "number of existing materials which have been updated: %d", - materialsToRegister.size(), materialUpdates.size())); - - } - - private static MaterialUpdateDTO createMaterialUpdate(Material existingMaterial, - NewMaterial material) - { - return new MaterialUpdateDTO(new TechId(existingMaterial.getId()), Arrays.asList(material - .getProperties()), existingMaterial.getModificationDate()); - } - - private void updateMaterials(String sessionToken, List<MaterialUpdateDTO> updates) - { - if (updates.size() == 0) - { - return; - } + assert sessionToken != null : "Unspecified session token."; final Session session = getSession(sessionToken); - IMaterialTable materialTable = businessObjectFactory.createMaterialTable(session); - materialTable.update(updates); - materialTable.save(); - } - - private Map<String/* code */, Material> listMaterials(String sessionToken, - String materialTypeCode) - { - checkSession(sessionToken); - EntityTypePE entityTypePE = - getDAOFactory().getEntityTypeDAO(EntityKind.MATERIAL).tryToFindEntityTypeByCode( - materialTypeCode); - MaterialType materialType = MaterialTypeTranslator.translateSimple(entityTypePE); - List<Material> materials = - commonServer.listMaterials(sessionToken, new ListMaterialCriteria(materialType), - false); - return asCodeToMaterialMap(materials); - } - - private static Map<String, Material> asCodeToMaterialMap(List<Material> materials) - { - Map<String, Material> map = new HashMap<String, Material>(); - for (Material material : materials) - { - map.put(material.getCode(), material); - } - return map; + getMaterialHelper(session).registerOrUpdateMaterials(materialTypeCode, materials); } public void registerExperiments(String sessionToken, NewExperimentsWithType experiments) @@ -888,4 +701,12 @@ public final class GenericServer extends AbstractServer<IGenericServer> implemen return experiments; } + private MaterialHelper getMaterialHelper(final Session session) + { + final MaterialHelper materialHelper = + new MaterialHelper(session, businessObjectFactory, getDAOFactory(), + getPropertiesBatchManager()); + return materialHelper; + } + } 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 cd36a3b09851a29a09574a103e11f17505b2c92c..eadeb1dd2ae45f898481effecef713a6f9550c4b 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 @@ -16,13 +16,12 @@ package ch.systemsx.cisd.openbis.plugin.generic.server; +import ch.systemsx.cisd.openbis.generic.server.business.bo.IAbstractBussinessObjectFactory; import ch.systemsx.cisd.openbis.generic.server.business.bo.IDataBO; import ch.systemsx.cisd.openbis.generic.server.business.bo.IDataSetTable; import ch.systemsx.cisd.openbis.generic.server.business.bo.IExperimentBO; import ch.systemsx.cisd.openbis.generic.server.business.bo.IExperimentTable; import ch.systemsx.cisd.openbis.generic.server.business.bo.IInvalidationBO; -import ch.systemsx.cisd.openbis.generic.server.business.bo.IMaterialBO; -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; @@ -34,7 +33,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.Session; * * @author Christian Ribeaud */ -public interface IGenericBusinessObjectFactory +public interface IGenericBusinessObjectFactory extends IAbstractBussinessObjectFactory { /** * Creates a {@link ISampleBO} <i>Business Object</i>. @@ -56,11 +55,6 @@ public interface IGenericBusinessObjectFactory */ public IExperimentBO createExperimentBO(final Session session); - /** - * Creates a {@link IMaterialBO} <i>Business Object</i>. - */ - public IMaterialBO createMaterialBO(final Session session); - /** * Creates a {@link IDataBO} <i>Business Object</i>. */ @@ -71,11 +65,6 @@ public interface IGenericBusinessObjectFactory */ public ISampleTable createSampleTable(final Session session); - /** - * Creates a {@link IMaterialTable} <i>Business Object</i>. - */ - public IMaterialTable createMaterialTable(Session session); - /** * Creates a {@link IDataSetTable} <i>Business Object</i>. */ diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceTest.java index 3ea32e1518a9226db55cf9883e5ece79e19bf809..2c63bb0434bbf80823a1776925e0d149c17c6a3b 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceTest.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceTest.java @@ -23,9 +23,11 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.Set; import org.hamcrest.BaseMatcher; @@ -57,6 +59,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListOrSearchSampleCriteria; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment; 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.NewProject; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSpace; @@ -81,6 +84,8 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.DatastoreServiceDescriptions; import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalDataPE; import ch.systemsx.cisd.openbis.generic.shared.dto.InvalidationPE; +import ch.systemsx.cisd.openbis.generic.shared.dto.MaterialPE; +import ch.systemsx.cisd.openbis.generic.shared.dto.MaterialTypePE; import ch.systemsx.cisd.openbis.generic.shared.dto.NewExternalData; import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE; import ch.systemsx.cisd.openbis.generic.shared.dto.PropertyTypePE; @@ -93,6 +98,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.SampleTypePE; import ch.systemsx.cisd.openbis.generic.shared.dto.SampleTypePropertyTypePE; 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.builders.DatabaseInstancePEBuilder; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.DatabaseInstanceIdentifier; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier; import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind; @@ -914,6 +920,17 @@ public class ETLServiceTest extends AbstractServerTestCase new SampleUpdatesDTO(CommonTestUtils.TECH_ID, null, null, attachments, version, sampleIdentifier, null, null); + final MaterialPE material = new MaterialPE(); + material.setCode("new-material"); + final MaterialTypePE materialType = new MaterialTypePE(); + materialType.setCode("new-material-type"); + materialType.setDatabaseInstance(new DatabaseInstancePEBuilder().code("db") + .getDatabaseInstance()); + final NewMaterial newMaterial = new NewMaterial(material.getCode()); + Map<String, List<NewMaterial>> materialRegistrations = + new HashMap<String, List<NewMaterial>>(); + materialRegistrations.put(materialType.getCode(), Arrays.asList(newMaterial)); + final SamplePE newSamplePE = createSampleWithExperiment(experiment); newSamplePE.setCode("sample code new"); final SampleIdentifier newSampleIdentifier = newSamplePE.getSampleIdentifier(); @@ -932,6 +949,30 @@ public class ETLServiceTest extends AbstractServerTestCase dataSetUpdate.setModifiedContainedDatasetCodesOrNull(new String[] { "c1", "c2" }); + context.checking(new Expectations() + { + { + allowing(daoFactory).getEntityTypeDAO(EntityKind.MATERIAL); + will(returnValue(entityTypeDAO)); + + allowing(entityTypeDAO).tryToFindEntityTypeByCode( + materialType.getCode()); + will(returnValue(materialType)); + + final List<NewMaterial> newMaterials = Arrays.asList(newMaterial); + one(propertiesBatchManager).manageProperties(materialType, newMaterials, null); + + one(boFactory).createMaterialTable(SESSION); + will(returnValue(materialTable)); + + one(materialTable).add(newMaterials, materialType); + one(materialTable).save(); + one(materialTable).getMaterials(); + will(returnValue(Arrays.asList(material))); + + } + }); + context.checking(new Expectations() { { @@ -998,7 +1039,7 @@ public class ETLServiceTest extends AbstractServerTestCase new AtomicEntityOperationDetails(null, new ArrayList<NewSpace>(), new ArrayList<NewProject>(), new ArrayList<NewExperiment>(), Collections.singletonList(sampleUpdate), - Collections.singletonList(newSample), + Collections.singletonList(newSample), materialRegistrations, Collections.singletonList(externalData), Collections.singletonList(dataSetUpdate)); 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 2d773460d3d1eaf935f1f4cf6c5f9ab6e9fa988e..cc540753cfed2db318a3aaf23c37eb72510146fa 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 @@ -57,6 +57,8 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentType; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListSampleCriteria; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialIdentifier; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewExperiment; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSamplesWithTypes; @@ -120,20 +122,11 @@ public interface IETLLIMSService extends IServer, ISessionProvider throws UserFailureException; /** - * Gets a sample with the specified identifier. Sample is enriched with properties and the - * experiment with properties. - * - * @param sessionToken the user authentication token. Must not be <code>null</code>. - * @param sampleIdentifier an identifier which uniquely identifies the sample. - * @return <code>null</code> if no sample attached to an experiment could be found for given - * <var>sampleIdentifier</var>. + * For given {@link MaterialIdentifier} returns the corresponding {@link Material}. */ @Transactional(readOnly = true) @RolesAllowed(RoleWithHierarchy.SPACE_ETL_SERVER) - public Sample tryGetSampleWithExperiment( - final String sessionToken, - @AuthorizationGuard(guardClass = ExistingSampleOwnerIdentifierPredicate.class) final SampleIdentifier sampleIdentifier) - throws UserFailureException; + public Material tryGetMaterial(String sessionToken, MaterialIdentifier materialIdentifier); /** * Tries to get the identifier of sample with specified permanent ID. @@ -154,6 +147,22 @@ public interface IETLLIMSService extends IServer, ISessionProvider public ExperimentType getExperimentType(String sessionToken, String experimentTypeCode) throws UserFailureException; + /** + * Gets a sample with the specified identifier. Sample is enriched with properties and the + * experiment with properties. + * + * @param sessionToken the user authentication token. Must not be <code>null</code>. + * @param sampleIdentifier an identifier which uniquely identifies the sample. + * @return <code>null</code> if no sample attached to an experiment could be found for given + * <var>sampleIdentifier</var>. + */ + @Transactional(readOnly = true) + @RolesAllowed(RoleWithHierarchy.SPACE_ETL_SERVER) + public Sample tryGetSampleWithExperiment( + final String sessionToken, + @AuthorizationGuard(guardClass = ExistingSampleOwnerIdentifierPredicate.class) final SampleIdentifier sampleIdentifier) + throws UserFailureException; + /** * Returns a list of terms belonging to given vocabulary. */ diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AtomicEntityOperationDetailsTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AtomicEntityOperationDetailsTest.java index bcde99654f13964f64dc0927e77910b53c7b71ad..8dfee947408997b810d3162c8df0a9ced3d755b4 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AtomicEntityOperationDetailsTest.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AtomicEntityOperationDetailsTest.java @@ -17,7 +17,9 @@ package ch.systemsx.cisd.openbis.generic.shared.basic.dto; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.testng.AssertJUnit; import org.testng.annotations.Test; @@ -42,6 +44,16 @@ public class AtomicEntityOperationDetailsTest extends AssertJUnit spaceRegistrations.add(new NewSpace("SPACE1", "description", "adminUser1")); spaceRegistrations.add(new NewSpace("SPACE2", "description", "adminUser2")); + Map<String, List<NewMaterial>> materialRegistrations = + new HashMap<String, List<NewMaterial>>(); + List<NewMaterial> newMaterials1 = new ArrayList<NewMaterial>(); + newMaterials1.add(new NewMaterial("material-one")); + newMaterials1.add(new NewMaterial("material-two")); + List<NewMaterial> newMaterials2 = new ArrayList<NewMaterial>(); + newMaterials2.add(new NewMaterial("material-three")); + materialRegistrations.put("material-type-1", newMaterials1); + materialRegistrations.put("material-type-2", newMaterials2); + ArrayList<NewProject> projectRegistrations = new ArrayList<NewProject>(); projectRegistrations.add(new NewProject("/SPACE/P1", "description")); projectRegistrations.add(new NewProject("/SPACE/P2", "description")); @@ -73,7 +85,7 @@ public class AtomicEntityOperationDetailsTest extends AssertJUnit AtomicEntityOperationDetails details = new AtomicEntityOperationDetails(null, spaceRegistrations, projectRegistrations, experimentRegistrations, sampleUpdates, sampleRegistrations, - dataSetRegistrations, dataSetUpdates); + materialRegistrations, dataSetRegistrations, dataSetUpdates); assertEquals( "AtomicEntityOperationDetails[userIdOrNull=<null>" @@ -83,6 +95,7 @@ public class AtomicEntityOperationDetailsTest extends AssertJUnit + ",experimentRegistrations=[/SPACE/PROJECT/EXP-ID1, /SPACE/PROJECT/EXP-ID2]" + ",sampleUpdates=[]" + ",sampleRegistrations=[/SPACE/SAMPLE-ID1, /SPACE/SAMPLE-ID2]" + + ",materialRegistrations={material-type-1=[material-one, material-two], material-type-2=[material-three]}" + ",dataSetRegistrations=[NewExternalData[code=DATA-SET-CODE,type=<null>,fileFormat=<null>,properties=[]]]" + ",dataSetUpdates=[1]]", details.toString()); diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServerTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServerTest.java index 4b01f7a5526f800d75ccc81afc64bb42bed42dd7..e41ed0567f8b92266d046b05b8f108e0673a0ae8 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServerTest.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServerTest.java @@ -71,6 +71,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE; import ch.systemsx.cisd.openbis.generic.shared.dto.SampleRelationshipPE; import ch.systemsx.cisd.openbis.generic.shared.dto.SampleTypePE; import ch.systemsx.cisd.openbis.generic.shared.dto.SampleUpdatesDTO; +import ch.systemsx.cisd.openbis.generic.shared.dto.Session; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFactory; @@ -461,6 +462,7 @@ public final class GenericServerTest extends AbstractServerTestCase one(materialTable).add(newMaterials, materialTypePE); one(materialTable).save(); + one(materialTable).getMaterials(); } }); createServer().registerMaterials(SESSION_TOKEN, typeCode, newMaterials); @@ -564,8 +566,10 @@ public final class GenericServerTest extends AbstractServerTestCase } existingMaterials.add(createMaterial(createNewMaterial("A"))); - one(commonServer).listMaterials(with(SESSION_TOKEN), - with(new BaseMatcher<ListMaterialCriteria>() + one(genericBusinessObjectFactory) + .createMaterialLister(with(any(Session.class))); + will(returnValue(materialLister)); + one(materialLister).list(with(new BaseMatcher<ListMaterialCriteria>() { public boolean matches(Object item) {