diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingService.java new file mode 100644 index 0000000000000000000000000000000000000000..77c354c491fc142cf005efc0c22db3c817bd162d --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingService.java @@ -0,0 +1,109 @@ +/* + * 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.api.v1; + +import java.util.Collections; +import java.util.Map; +import java.util.Map.Entry; + +import javax.annotation.Resource; + +import org.springframework.stereotype.Component; + +import ch.systemsx.cisd.authentication.ISessionManager; +import ch.systemsx.cisd.common.spring.IInvocationLoggerContext; +import ch.systemsx.cisd.openbis.generic.server.AbstractServer; +import ch.systemsx.cisd.openbis.generic.server.business.IPropertiesBatchManager; +import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory; +import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationChangingService; +import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample; +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.ExperimentIdentifier; +import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifierFactory; +import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier; +import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFactory; +import ch.systemsx.cisd.openbis.generic.shared.util.EntityHelper; +import ch.systemsx.cisd.openbis.plugin.generic.shared.IGenericServer; + +/** + * + * + * @author Franz-Josef Elmer + */ +@Component(ResourceNames.GENERAL_INFORMATION_CHANGING_SERVICE_SERVER) +public class GeneralInformationChangingService extends + AbstractServer<IGeneralInformationChangingService> implements + IGeneralInformationChangingService +{ + @Resource(name = ch.systemsx.cisd.openbis.plugin.generic.shared.ResourceNames.GENERIC_PLUGIN_SERVER) + private IGenericServer genericServer; + + // Default constructor needed by Spring + public GeneralInformationChangingService() + { + } + + GeneralInformationChangingService(ISessionManager<Session> sessionManager, IDAOFactory daoFactory, + IPropertiesBatchManager propertiesBatchManager, IGenericServer genericServer) + { + super(sessionManager, daoFactory, propertiesBatchManager); + this.genericServer = genericServer; + } + + public IGeneralInformationChangingService createLogger(IInvocationLoggerContext context) + { + return new GeneralInformationChangingServiceLogger(sessionManager, context); + } + + public void updateSampleProperties(String sessionToken, long sampleID, + Map<String, String> properties) + { + TechId id = new TechId(sampleID); + Sample sample = genericServer.getSampleInfo(sessionToken, id).getParent(); + for (Entry<String, String> entry : properties.entrySet()) + { + EntityHelper.createOrUpdateProperty(sample, entry.getKey(), entry.getValue()); + } + Experiment experiment = sample.getExperiment(); + ExperimentIdentifier experimentIdentifier = + experiment == null ? null : ExperimentIdentifierFactory.parse(experiment + .getIdentifier()); + SampleIdentifier sampleIdentifier = SampleIdentifierFactory.parse(sample.getIdentifier()); + Sample container = sample.getContainer(); + String containerIdentifier = container == null ? null : container.getIdentifier(); + SampleUpdatesDTO updates = + new SampleUpdatesDTO(id, sample.getProperties(), experimentIdentifier, + Collections.<NewAttachment> emptySet(), sample.getModificationDate(), + sampleIdentifier, containerIdentifier, null); + genericServer.updateSample(sessionToken, updates); + } + + public int getMajorVersion() + { + return 1; + } + + public int getMinorVersion() + { + return 0; + } + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingServiceLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingServiceLogger.java new file mode 100644 index 0000000000000000000000000000000000000000..0beb69b34ff8a167f97fe58a1acc9391045de9bf --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingServiceLogger.java @@ -0,0 +1,58 @@ +/* + * 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.api.v1; + +import java.util.Map; + +import ch.systemsx.cisd.authentication.ISessionManager; +import ch.systemsx.cisd.common.spring.IInvocationLoggerContext; +import ch.systemsx.cisd.openbis.generic.shared.AbstractServerLogger; +import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationChangingService; +import ch.systemsx.cisd.openbis.generic.shared.dto.Session; + +/** + * + * + * @author Franz-Josef Elmer + */ +class GeneralInformationChangingServiceLogger extends AbstractServerLogger implements + IGeneralInformationChangingService +{ + + public GeneralInformationChangingServiceLogger(ISessionManager<Session> sessionManagerNull, + IInvocationLoggerContext context) + { + super(sessionManagerNull, context); + } + + public void updateSampleProperties(String sessionToken, long sampleID, + Map<String, String> properties) + { + logTracking(sessionToken, "update-sample-properties", "SAMPLE(%s)", sampleID); + } + + public int getMajorVersion() + { + return 0; + } + + public int getMinorVersion() + { + return 0; + } + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingServiceServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingServiceServer.java new file mode 100644 index 0000000000000000000000000000000000000000..b5dc8066e9a9e0f74654e4b4e0c07cd06549db13 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingServiceServer.java @@ -0,0 +1,47 @@ +/* + * 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.server.api.v1; + +import javax.annotation.Resource; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +import ch.systemsx.cisd.common.api.server.AbstractApiServiceExporter; +import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationChangingService; + +/** + * + * + * @author Franz-Josef Elmer + */ +@Controller +@RequestMapping( + { IGeneralInformationChangingService.SERVICE_URL, "/openbis" + IGeneralInformationChangingService.SERVICE_URL }) +public class GeneralInformationChangingServiceServer extends AbstractApiServiceExporter +{ + @Resource(name = ResourceNames.GENERAL_INFORMATION_CHANGING_SERVICE_SERVER) + private IGeneralInformationChangingService service; + + @Override + public void afterPropertiesSet() + { + establishService(IGeneralInformationChangingService.class, service, + IGeneralInformationChangingService.SERVICE_NAME, IGeneralInformationChangingService.SERVICE_URL); + super.afterPropertiesSet(); + } +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/ResourceNames.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/ResourceNames.java index 5ce924a871e6d191b5eac019f96e16564a68cdcd..1fdb8174c752653d561a0fd847cd27e59c39ee78 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/ResourceNames.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/ResourceNames.java @@ -24,5 +24,6 @@ package ch.systemsx.cisd.openbis.generic.server.api.v1; public class ResourceNames { public final static String GENERAL_INFORMATION_SERVICE_SERVER = "general-information-api-server-v1"; + public final static String GENERAL_INFORMATION_CHANGING_SERVICE_SERVER = "general-information-changing-api-server-v1"; } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/Translator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/Translator.java index 5b64b638eb98f3720b7b82295035dcf4713990c0..e634f79a7d25794dbd4fb0b182078e9bebb71bc8 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/Translator.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/Translator.java @@ -73,7 +73,7 @@ public class Translator List<IEntityProperty> properties = privateSample.getProperties(); for (IEntityProperty prop : properties) { - initializer.putProperty(prop.getPropertyType().getCode(), prop.getValue()); + initializer.putProperty(prop.getPropertyType().getCode(), prop.tryGetAsString()); } ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment experimentOrNull = diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityPropertiesConverter.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityPropertiesConverter.java index 56566e83e8831ec945db588fe205a9f64bd02d72..6c290f75a73a0af8c2b5d7a1567f1ffe1e81440c 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityPropertiesConverter.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityPropertiesConverter.java @@ -413,7 +413,8 @@ public final class EntityPropertiesConverter implements IEntityPropertiesConvert final Set<T> set = new HashSet<T>(); for (T newProperty : convertedProperties) { - T existingProperty = tryFind(oldProperties, newProperty); + PropertyTypePE propertyType = newProperty.getEntityTypePropertyType().getPropertyType(); + T existingProperty = tryFind(oldProperties, propertyType); if (existingProperty != null) { existingProperty.setUntypedValue(newProperty.getValue(), @@ -478,12 +479,12 @@ public final class EntityPropertiesConverter implements IEntityPropertiesConvert return set; } - private static <T extends EntityPropertyPE> T tryFind(Collection<T> oldProperties, T p) + private static <T extends EntityPropertyPE> T tryFind(Collection<T> oldProperties, PropertyTypePE propertyType) { for (T oldProperty : oldProperties) { if (oldProperty.getEntityTypePropertyType().getPropertyType() - .equals(p.getEntityTypePropertyType().getPropertyType())) + .equals(propertyType)) { return oldProperty; } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationChangingService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationChangingService.java new file mode 100644 index 0000000000000000000000000000000000000000..ce933733549ea883f8b713650aa44ac2c1577836 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationChangingService.java @@ -0,0 +1,47 @@ +/* + * 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.shared.api.v1; + +import java.util.Map; + +import org.springframework.transaction.annotation.Transactional; + +import ch.systemsx.cisd.common.api.IRpcService; +import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RolesAllowed; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy; + +/** + * Service for changing general informations. + * + * @author Franz-Josef Elmer + */ +public interface IGeneralInformationChangingService extends IRpcService +{ + /** + * Name of this service for which it is registered at the RPC name server. + */ + public static final String SERVICE_NAME = "general-information-changing"; + + /** + * Application part of the URL to access this service remotely. + */ + public static final String SERVICE_URL = "/rmi-" + SERVICE_NAME + "-v1"; + + @Transactional + @RolesAllowed(RoleWithHierarchy.SPACE_USER) + public void updateSampleProperties(String sessionToken, long sampleID, Map<String, String> properties); +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/EntityHelper.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/EntityHelper.java index ba17689f1a5e0bf83cc9df00da2250efe0ac7f40..bbbecc87376ea063307d33fcfa2420a1b76dfbd2 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/EntityHelper.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/EntityHelper.java @@ -121,20 +121,25 @@ public class EntityHelper } /** - * Tries to set the value for a given property in an {@link IEntityPropertiesHolder} instance. - * Creates a new property if no property for the specified code is found. + * Creates a property with specified code and value. An already existing property with same + * code will be removed. */ public static void createOrUpdateProperty(IEntityPropertiesHolder holder, String propertyCode, String propertyValue) { - IEntityProperty property = tryFindProperty(holder.getProperties(), propertyCode); - - if (property == null) + IEntityProperty newProperty = createNewProperty(propertyCode, propertyValue); + List<IEntityProperty> properties = holder.getProperties(); + for (int i = 0; i < properties.size(); i++) { - property = createNewProperty(propertyCode); - holder.getProperties().add(property); + IEntityProperty property = properties.get(i); + PropertyType propertyType = property.getPropertyType(); + if (propertyType.getCode().equalsIgnoreCase(propertyCode)) + { + properties.set(i, newProperty); + return; + } } - property.setValue(propertyValue); + properties.add(newProperty); } public static IEntityProperty createNewProperty(String propertyCode, String propertyValue) diff --git a/screening/build/build.xml b/screening/build/build.xml index 63ad0254d852b86be8742630f5d1ef0e4fb4fc03..51d39cd7777532e62ae30ba34eb17a303b4e0b1e 100644 --- a/screening/build/build.xml +++ b/screening/build/build.xml @@ -373,6 +373,79 @@ </zip> </target> + + <target name="screening-api-eclipse"> + <mkdir dir="${dist.screening-api.lib}" /> + <recursive-jar destfile="${dist.screening-api.jar}"> + <fileset dir="${targets}/www/WEB-INF/classes"> + <include name="OpenBISScreeningML*.class" /> + <include name="ch/systemsx/cisd/common/api/**/*.class" /> + <exclude name="ch/systemsx/cisd/common/api/server/**/*.class" /> + <include name="ch/systemsx/cisd/openbis/dss/client/api/v1/**/*.class" /> + <include name="ch/systemsx/cisd/openbis/dss/generic/shared/api/v1/**/*.class" /> + <include name="ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/**/*.class" /> + <include name="ch/systemsx/cisd/openbis/dss/screening/shared/api/**/*.class" /> + <include name="ch/systemsx/cisd/openbis/generic/shared/basic/**/*.class" /> + <include name="ch/systemsx/cisd/openbis/generic/shared/api/**/*.class" /> + <include name="ch/systemsx/cisd/openbis/generic/shared/authorization/annotation/**/*.class" /> + <include name="ch/systemsx/cisd/openbis/plugin/screening/shared/api/**/*.class" /> + <include name="ch/systemsx/cisd/openbis/plugin/screening/client/api/**/*.class" /> + <include name="ch/systemsx/cisd/openbis/plugin/screening/client/cli/**/*.class" /> + </fileset> + <manifest> + <attribute name="Main-Class" value="ch.systemsx.cisd.openbis.plugin.screening.client.api.v1.ScreeningClientApiTest" /> + <attribute name="Class-Path" value="spring-ext.jar" /> + <attribute name="Version" value="${version.number}" /> + <attribute name="Build-Number" + value="${version.number} (r${revision.number},${clean.flag})" /> + </manifest> + </recursive-jar> + <jar update="true" destfile="${dist.screening-api.jar}"> + <fileset dir="../openbis/targets/www/WEB-INF/classes"> + <include name="ch/systemsx/cisd/openbis/generic/client/cli/Login*.class" /> + <include name="ch/systemsx/cisd/openbis/generic/shared/api/v1/**/*.class" /> + </fileset> + <fileset dir="../datastore_server/targets/classes"> + <include name="ch/systemsx/cisd/openbis/dss/client/api/v1/**/*.class" /> + <include name="ch/systemsx/cisd/openbis/dss/generic/shared/api/v1/**/*.class" /> + <include name="ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/**/*.class" /> + </fileset> + <fileset dir="../server-common/targets/classes"> + <include name="ch/systemsx/cisd/common/spring/HttpInvokerUtils.class" /> + <include name="ch/systemsx/cisd/common/api/client/**/*.class" /> + </fileset> + <fileset dir="../common/targets/classes"> + <include name="ch/systemsx/cisd/common/exceptions/**/*.class" /> + <include name="ch/systemsx/cisd/common/api/*.class" /> + <include name="ch/systemsx/cisd/common/io/ConcatenatedFileOutputStreamWriter.class" /> + <include name="ch/systemsx/cisd/common/io/ConcatenatedContentInputStream.class" /> + <include name="ch/systemsx/cisd/common/io/FileBasedContent.class" /> + <include name="ch/systemsx/cisd/common/io/IContent.class" /> + </fileset> + </jar> + <zip update="true" destfile="${dist.screening-api.jar}"> + <zipfileset src="${lib}/gwt2.0/gwt-user.jar"> + <include name="com/google/gwt/user/client/rpc/IsSerializable.class" /> + <include name="com/google/gwt/user/client/rpc/SerializableException.class" /> + </zipfileset> + </zip> + <recursive-jar destfile="${dist.screening-api.lib}/spring-ext.jar"> + <zipfileset src="${lib}/spring/spring.jar" /> + <zipfileset src="${lib}/spring/third-party/stream-supporting-httpinvoker.jar" /> + <zipfileset src="${lib}/commons-logging/commons-logging.jar" /> + <zipfileset src="${lib}/commons-httpclient/commons-httpclient.jar" /> + <zipfileset src="${lib}/commons-codec/commons-codec.jar" /> + <zipfileset src="${lib}/log4j/log4j.jar" /> + <zipfileset src="${lib}/jline/jline.jar" /> + <zipfileset src="${lib}/cisd-args4j/cisd-args4j.jar" /> + <zipfileset src="${lib}/cisd-base/cisd-base.jar" /> + <zipfileset src="${lib}/jython/standalone/jython.jar" /> + </recursive-jar> + <recursive-jar destfile="${dist.screening-api-batteries-included.jar}"> + <zipfileset src="${dist.screening-api.lib}/spring-ext.jar" /> + <zipfileset src="${dist.screening-api.jar}" /> + </recursive-jar> + </target> <!-- To test the API you can use diff --git a/screening/source/java/OpenBISScreeningML.java b/screening/source/java/OpenBISScreeningML.java index b6eb5b299b29a71db2d2fb3d721ee6a5b2e1f0f4..6c00533f8c58042989ff21b51264adf17ee54887 100644 --- a/screening/source/java/OpenBISScreeningML.java +++ b/screening/source/java/OpenBISScreeningML.java @@ -28,7 +28,6 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Properties; import ch.systemsx.cisd.openbis.dss.client.api.v1.IDataSetDss; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.NewDataSetMetadataDTO; @@ -49,6 +48,7 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.Plate; import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.PlateIdentifier; import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.PlateImageReference; import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.PlateWellMaterialMapping; +import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.WellIdentifier; import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.WellPosition; /** @@ -84,6 +84,9 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.WellPosition; */ public class OpenBISScreeningML { + + static final String DATASETS_FOLDER = "openbis_datasets"; + private static interface ITileNumberIterable extends Iterable<Integer> { public void setMaximumNumberOfTiles(int numberOfTiles); @@ -175,6 +178,15 @@ public class OpenBISScreeningML private static File dataSetsDir; + /** + * Root temporary directory for data sets and images. By default <code>java.io.tmpdir</code> is + * used. + */ + static File tempDir = new File(System.getProperty("java.io.tmpdir")); + + static final String TEMP_DIR_PREFIX = "openbis_"; + static final String TEMP_DIR_POSTFIX = "_temp_dir"; + // // Authentication methods // @@ -194,23 +206,23 @@ public class OpenBISScreeningML */ public static void login(String user, String password, String url) { - openbis = ScreeningOpenbisServiceFacadeFactory.tryCreate(user, password, url); - if (openbis == null) + IScreeningOpenbisServiceFacade facade = ScreeningOpenbisServiceFacadeFactory.tryCreate(user, password, url); + if (facade == null) { throw new RuntimeException("Login failed."); } - init(); + init(facade); } - private static void init() + public static void init(IScreeningOpenbisServiceFacade openBisFacade) { - File tempDir = new File(System.getProperty("java.io.tmpdir")); - dataSetsDir = new File(tempDir, "openbis_datasets"); + openbis = openBisFacade; + dataSetsDir = new File(tempDir, DATASETS_FOLDER); if (dataSetsDir.isDirectory() == false && dataSetsDir.mkdirs() == false) { throw new RuntimeException("Couldn't create a data set directory."); } - temporarySessionDir = new File(tempDir, "openbis_" + System.currentTimeMillis() / 1000 + "_temp_dir"); + temporarySessionDir = new File(tempDir, TEMP_DIR_PREFIX + System.currentTimeMillis() / 1000 + TEMP_DIR_POSTFIX); if (temporarySessionDir.mkdirs() == false) { throw new RuntimeException("Couldn't create a temporary directory."); @@ -260,8 +272,22 @@ public class OpenBISScreeningML { Login.OPENBIS_TOKEN_FILE.delete(); } + delete(temporarySessionDir); openbis = null; } + + private static void delete(File file) + { + if (file.isDirectory()) + { + File[] files = file.listFiles(); + for (File child : files) + { + delete(child); + } + } + file.delete(); + } // // Information methods @@ -330,21 +356,7 @@ public class OpenBISScreeningML public static Object[][] listPlates() { checkLoggedIn(); - final Object[][] result = new Object[plates.size()][9]; - for (int i = 0; i < plates.size(); ++i) - { - final Object[] annotations = - new Object[] - { plates.get(i).getAugmentedCode(), plates.get(i).getPermId(), - plates.get(i).tryGetSpaceCode(), plates.get(i).getPlateCode(), - plates.get(i).getExperimentIdentifier().getAugmentedCode(), - plates.get(i).getExperimentIdentifier().getPermId(), - plates.get(i).getExperimentIdentifier().getSpaceCode(), - plates.get(i).getExperimentIdentifier().getProjectCode(), - plates.get(i).getExperimentIdentifier().getExperimentCode(), }; - System.arraycopy(annotations, 0, result[i], 0, annotations.length); - } - return result; + return listPlates(plates); } /** @@ -378,27 +390,110 @@ public class OpenBISScreeningML { throw new RuntimeException("No experiment with that code found."); } - final Object[][] result = new Object[experimentPlates.size()][9]; - for (int i = 0; i < experimentPlates.size(); ++i) + return listPlates(experimentPlates); + } + + private static Object[][] listPlates(final List<Plate> list) + { + final Object[][] result = new Object[list.size()][9]; + for (int i = 0; i < list.size(); ++i) { final Object[] annotations = new Object[] { - experimentPlates.get(i).getAugmentedCode(), + list.get(i).getAugmentedCode(), plates.get(i).getPermId(), - experimentPlates.get(i).tryGetSpaceCode(), + list.get(i).tryGetSpaceCode(), plates.get(i).getPlateCode(), - experimentPlates.get(i).getExperimentIdentifier() + list.get(i).getExperimentIdentifier() .getAugmentedCode(), - experimentPlates.get(i).getExperimentIdentifier().getPermId(), - experimentPlates.get(i).getExperimentIdentifier().getSpaceCode(), - experimentPlates.get(i).getExperimentIdentifier().getProjectCode(), - experimentPlates.get(i).getExperimentIdentifier() + list.get(i).getExperimentIdentifier().getPermId(), + list.get(i).getExperimentIdentifier().getSpaceCode(), + list.get(i).getExperimentIdentifier().getProjectCode(), + list.get(i).getExperimentIdentifier() .getExperimentCode(), }; System.arraycopy(annotations, 0, result[i], 0, annotations.length); } return result; } + + /** + * Returns the properties of specified well for specified plate. + * <p> + * Matlab example: + * + * <pre> + * % Get properties for well A03 of plate P005 in space SPACE + * properties = OpenBISScreeningML.getWellProperties('/SPACE/P005', 1, 3, properties) + * % Get property type code of first property + * properties(1,1) + * % Get property value of first property + * properties(1,2) + * </pre> + * + * @param augmentedPlateCode The augmented plate code + * @param row The row in the plate to get the well properties for + * @param column The column in the plate to get the well properties for + * @return A two dimensional array where the first column contains the property + * codes and the second column the corresponding property values. + */ + public static Object[][] getWellProperties(String augmentedPlateCode, int row, + int column) + { + checkLoggedIn(); + WellPosition wellPosition = new WellPosition(row, column); + WellIdentifier wellIdentifier = getWell(augmentedPlateCode, wellPosition); + List<Map.Entry<String, String>> list = + new ArrayList<Map.Entry<String, String>>(openbis.getWellProperties(wellIdentifier) + .entrySet()); + Object[][] result = new Object[list.size()][2]; + for (int i = 0; i < list.size(); i++) + { + result[i] = new Object[] {list.get(i).getKey(), list.get(i).getValue()}; + } + return result; + } + + /** + * Updates properties of specified well for specified plate. + * <p> + * Matlab example: + * + * <pre> + * % Updates properties DESCRIPTION and NUMBER for well A03 of plate P005 in space SPACE + * properties = {'DESCRIPTION' 'hello example'; 'NUMBER' 3.14} + * OpenBISScreeningML.updateWellProperties('/SPACE/P005', 1, 3, properties) + * </pre> + * + * @param augmentedPlateCode The augmented plate code + * @param row The row in the plate to get the well properties for + * @param column The column in the plate to get the well properties for + * @param properties A two dimensional array where the first column contains the property + * codes and the second column the corresponding property values. + */ + public static void updateWellProperties(String augmentedPlateCode, int row, + int column, Object[][] properties) + { + checkLoggedIn(); + WellPosition wellPosition = new WellPosition(row, column); + WellIdentifier wellIdentifier = getWell(augmentedPlateCode, wellPosition); + openbis.updateWellProperties(wellIdentifier, createMap(properties)); + } + + private static WellIdentifier getWell(String augmentedPlateCode, WellPosition wellPosition) + { + Plate plate = getPlate(augmentedPlateCode); + List<WellIdentifier> wells = openbis.listPlateWells(plate); + for (WellIdentifier wellIdentifier : wells) + { + if (wellIdentifier.getWellPosition().equals(wellPosition)) + { + return wellIdentifier; + } + } + throw new RuntimeException("Plate '" + augmentedPlateCode + "' has now well at " + + wellPosition + "."); + } /** * Lists all channels measured in <var>experiment</var>. @@ -522,7 +617,7 @@ public class OpenBISScreeningML * * <pre> * % Load all data sets of plate P005 in space SPACE - * dsinfo = loadDataSets('/SPACE/P005') + * dsinfo = OpenBISScreeningML.loadDataSets('/SPACE/P005') * % Get the data set codes * dsinfo(:,1) * % Get root path of first data set (assuming there is at least one) @@ -545,12 +640,13 @@ public class OpenBISScreeningML for (int i = 0; i < dataSets.size(); i++) { IDataSetDss dataSet = dataSets.get(i); - File file = new File(dataSetsDir, dataSet.getCode()); + String code = dataSet.getCode(); + File file = new File(dataSetsDir, code); if (file.exists() == false) { file = dataSet.getLinkOrCopyOfContents(null, dataSetsDir); } - result[i] = new Object[] {dataSet.getCode(), file.getPath()}; + result[i] = new Object[] {code, file.getPath()}; } return result; } catch (Exception ex) @@ -569,7 +665,7 @@ public class OpenBISScreeningML * % Upload data set /path/to/my-data-set with properties DESCRIPTION and NUMBER for * % plate P005 in space SPACE * properties = {'DESCRIPTION' 'hello example'; 'NUMBER' 3.14} - * datasetcode = uploadDataSet('/SPACE/P005', '/path/to/my-data-set', 'HCS_IMAGE', properties) + * datasetcode = OpenBISScreeningML.uploadDataSet('/SPACE/P005', '/path/to/my-data-set', 'HCS_IMAGE', properties) * </pre> * * @param augmentedPlateCode The augmented plate code. @@ -590,14 +686,7 @@ public class OpenBISScreeningML } try { - HashMap<String, String> map = new HashMap<String, String>(); - for (Object[] objects : dataSetProperties) - { - if (objects.length == 2) - { - map.put(objects[0].toString(), objects[1].toString()); - } - } + Map<String, String> map = createMap(dataSetProperties); IDataSetDss dataSet = openbis.putDataSet(plateIdentifier, dataSetFile, new NewDataSetMetadataDTO( dataSetType, map)); @@ -609,10 +698,20 @@ public class OpenBISScreeningML } } - public static Object testProperties(Properties properties) + private static Map<String, String> createMap(Object[][] properties) { - return properties.toString(); + Map<String, String> map = new HashMap<String, String>(); + for (Object[] objects : properties) + { + if (objects.length == 2) + { + Object value = objects[1]; + map.put(objects[0].toString(), value == null ? null : value.toString()); + } + } + return map; } + // // Images // @@ -1502,12 +1601,12 @@ public class OpenBISScreeningML final String serverUrl = br.readLine(); br.close(); br = null; - openbis = ScreeningOpenbisServiceFacadeFactory.tryCreate(token, serverUrl); - if (openbis == null) + IScreeningOpenbisServiceFacade facade = ScreeningOpenbisServiceFacadeFactory.tryCreate(token, serverUrl); + if (facade == null) { throw new RuntimeException("Login failed."); } - init(); + init(facade); } catch (IOException ex) { if (openbis == null) diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/IScreeningOpenbisServiceFacade.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/IScreeningOpenbisServiceFacade.java index 3337f157e649c43e7db31b290884c5cfe5ea0bb7..130c9cc4e28b9a20378b6115d24ff239bc961df6 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/IScreeningOpenbisServiceFacade.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/IScreeningOpenbisServiceFacade.java @@ -19,6 +19,7 @@ package ch.systemsx.cisd.openbis.plugin.screening.client.api.v1; import java.io.File; import java.io.IOException; import java.util.List; +import java.util.Map; import ch.systemsx.cisd.base.image.IImageTransformerFactory; import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; @@ -149,6 +150,16 @@ public interface IScreeningOpenbisServiceFacade * For the given <var>plateIdentifier</var> find all wells that are connected to it. */ public List<WellIdentifier> listPlateWells(PlateIdentifier plateIdentifier); + + /** + * Returns all properties of specified well as a map. + */ + public Map<String, String> getWellProperties(WellIdentifier wellIdentifier); + + /** + * Updates properties of specified well. + */ + public void updateWellProperties(WellIdentifier wellIdentifier, Map<String, String> properties); /** * Get proxies to the data sets owned by specified well. @@ -555,5 +566,5 @@ public interface IScreeningOpenbisServiceFacade public List<PlateWellMaterialMapping> listPlateMaterialMapping( List<? extends PlateIdentifier> plates, MaterialTypeIdentifier materialTypeIdentifierOrNull); - + } \ No newline at end of file diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/ScreeningOpenbisServiceFacade.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/ScreeningOpenbisServiceFacade.java index de265892d2a30413c53a28a770a90d97fd332328..069dcc63bcad811cb3119ba62fe254b723d96ec6 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/ScreeningOpenbisServiceFacade.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/ScreeningOpenbisServiceFacade.java @@ -35,6 +35,7 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.NewDataSetDTO.DataSetO import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.NewDataSetDTO.DataSetOwnerType; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.NewDataSetMetadataDTO; import ch.systemsx.cisd.openbis.dss.screening.shared.api.v1.IDssServiceRpcScreening; +import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationChangingService; import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationService; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSet; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Sample; @@ -92,6 +93,8 @@ public class ScreeningOpenbisServiceFacade implements IScreeningOpenbisServiceFa private final IScreeningApiServer openbisScreeningServer; private final IGeneralInformationService generalInformationService; + + private final IGeneralInformationChangingService generalInformationChangingService; private final IDssComponent dssComponent; @@ -126,18 +129,12 @@ public class ScreeningOpenbisServiceFacade implements IScreeningOpenbisServiceFa String serverUrl) { final IScreeningApiServer openbisServer = createScreeningOpenbisServer(serverUrl); - final IGeneralInformationService generalInformationService = - createGeneralInformationService(serverUrl); - final int minorVersion = openbisServer.getMinorVersion(); final String sessionToken = openbisServer.tryLoginScreening(userId, userPassword); if (sessionToken == null) { return null; } - final IDssComponent dssComponent = - DssComponentFactory.tryCreate(sessionToken, serverUrl, SERVER_TIMEOUT_MILLIS); - return new ScreeningOpenbisServiceFacade(sessionToken, openbisServer, minorVersion, - DSS_SERVICE_FACTORY, dssComponent, generalInformationService); + return tryCreate(sessionToken, serverUrl, openbisServer); } /** @@ -149,14 +146,22 @@ public class ScreeningOpenbisServiceFacade implements IScreeningOpenbisServiceFa */ public static IScreeningOpenbisServiceFacade tryCreate(String sessionToken, String serverUrl) { - final IScreeningApiServer openbisServer = createScreeningOpenbisServer(serverUrl); + return tryCreate(sessionToken, serverUrl, createScreeningOpenbisServer(serverUrl)); + } + + private static IScreeningOpenbisServiceFacade tryCreate(String sessionToken, String serverUrl, + final IScreeningApiServer openbisServer) + { final IGeneralInformationService generalInformationService = createGeneralInformationService(serverUrl); + IGeneralInformationChangingService generalInformationChangingService = + createGeneralInformationChangingService(serverUrl); final int minorVersion = openbisServer.getMinorVersion(); final IDssComponent dssComponent = DssComponentFactory.tryCreate(sessionToken, serverUrl, SERVER_TIMEOUT_MILLIS); return new ScreeningOpenbisServiceFacade(sessionToken, openbisServer, minorVersion, - DSS_SERVICE_FACTORY, dssComponent, generalInformationService); + DSS_SERVICE_FACTORY, dssComponent, generalInformationService, + generalInformationChangingService); } private static IScreeningApiServer createScreeningOpenbisServer(String serverUrl) @@ -175,12 +180,25 @@ public class ScreeningOpenbisServiceFacade implements IScreeningOpenbisServiceFa return service; } + private static IGeneralInformationChangingService createGeneralInformationChangingService( + String serverUrl) + { + ServiceFinder generalInformationServiceFinder = + new ServiceFinder("openbis", IGeneralInformationChangingService.SERVICE_URL); + IGeneralInformationChangingService service = + generalInformationServiceFinder.createService( + IGeneralInformationChangingService.class, serverUrl); + return service; + } + ScreeningOpenbisServiceFacade(String sessionToken, IScreeningApiServer screeningServer, int minorVersion, final IDssServiceFactory dssServiceFactory, - IDssComponent dssComponent, IGeneralInformationService generalInformationService) + IDssComponent dssComponent, IGeneralInformationService generalInformationService, + IGeneralInformationChangingService generalInformationChangingService) { this.openbisScreeningServer = screeningServer; this.generalInformationService = generalInformationService; + this.generalInformationChangingService = generalInformationChangingService; this.dssComponent = dssComponent; this.sessionToken = sessionToken; this.minorVersionApplicationServer = minorVersion; @@ -365,6 +383,19 @@ public class ScreeningOpenbisServiceFacade implements IScreeningOpenbisServiceFa checkASMinimalMinorVersion("listPlateWells", PlateIdentifier.class); return openbisScreeningServer.listPlateWells(sessionToken, plateIdentifier); } + + public Map<String, String> getWellProperties(WellIdentifier wellIdentifier) + { + Sample wellSample = openbisScreeningServer.getWellSample(sessionToken, wellIdentifier); + Map<String, String> properties = wellSample.getProperties(); + return properties; + } + + public void updateWellProperties(WellIdentifier wellIdentifier, Map<String, String> properties) + { + Sample wellSample = openbisScreeningServer.getWellSample(sessionToken, wellIdentifier); + generalInformationChangingService.updateSampleProperties(sessionToken, wellSample.getId(), properties); + } /** * Get proxies to the data sets owned by specified well. diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/ScreeningServer.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/ScreeningServer.java index 7213a26b21c9d4c7d967857bd5878a4e32cb3c31..1f22d54c6627caa73f43d2b424970be5c74572d8 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/ScreeningServer.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/ScreeningServer.java @@ -375,7 +375,7 @@ public final class ScreeningServer extends AbstractServer<IScreeningServer> impl public Sample getWellSample(String sessionToken, WellIdentifier wellIdentifier) { - return createScreeningApiImpl(sessionToken).getWellSample(wellIdentifier); + return createScreeningApiImpl(sessionToken).getWellSample(wellIdentifier, true); } public Sample getPlateSample(String sessionToken, PlateIdentifier plateIdentifier) diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/ScreeningApiImpl.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/ScreeningApiImpl.java index 63768caeeb1184935c53f62cf6901bed430b4063..8044637a04f1d3ad5117381415f269b64ceca88f 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/ScreeningApiImpl.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/ScreeningApiImpl.java @@ -422,7 +422,7 @@ public class ScreeningApiImpl Sample sample; if (plateIdentifier.getPermId() != null) { - sample = loadSampleByPermId(plateIdentifier.getPermId()); + sample = loadSampleByPermId(plateIdentifier.getPermId(), false); } else { SampleIdentifier sampleIdentifier = createSampleIdentifier(plateIdentifier); @@ -434,9 +434,9 @@ public class ScreeningApiImpl } public ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Sample getWellSample( - WellIdentifier wellIdentifier) + WellIdentifier wellIdentifier, boolean enrichWithProperties) { - Sample sample = loadSampleByPermId(wellIdentifier.getPermId()); + Sample sample = loadSampleByPermId(wellIdentifier.getPermId(), enrichWithProperties); return Translator.translate(sample); } @@ -446,10 +446,14 @@ public class ScreeningApiImpl return Translator.translate(getSample(plateIdentifier)); } - private Sample loadSampleByPermId(String permId) + private Sample loadSampleByPermId(String permId, boolean enrichWithProperties) { ISampleBO sampleBO = businessObjectFactory.createSampleBO(session); sampleBO.loadBySamplePermId(permId); + if (enrichWithProperties) + { + sampleBO.enrichWithProperties(); + } SamplePE samplePE = sampleBO.getSample(); return translate(samplePE); } diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/IScreeningApiServer.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/IScreeningApiServer.java index 62b06910dc1bbb73e5f8382c92fab26762f21028..38f3ef90065d4700bd497d1dcd2059e6651c5a12 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/IScreeningApiServer.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/IScreeningApiServer.java @@ -231,7 +231,7 @@ public interface IScreeningApiServer extends IRpcService @AuthorizationGuard(guardClass = PlateIdentifierPredicate.class) PlateIdentifier plateIdentifier); /** - * For a given <var>wellIdentifier</var>, return the corresponding {@link Sample}. + * For a given <var>wellIdentifier</var>, return the corresponding {@link Sample} including properties. * * @since 1.3 */ diff --git a/screening/sourceTest/java/OpenBISScreeningMLTest.java b/screening/sourceTest/java/OpenBISScreeningMLTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4fa28e23817b3ceb99c359aaf599f61a7a682cd9 --- /dev/null +++ b/screening/sourceTest/java/OpenBISScreeningMLTest.java @@ -0,0 +1,532 @@ +/* + * 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. + */ + + + +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.Comparator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.jmock.Sequence; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel; +import ch.systemsx.cisd.base.tests.AbstractFileSystemTestCase; +import ch.systemsx.cisd.common.filesystem.FileUtilities; +import ch.systemsx.cisd.common.test.RecordingMatcher; +import ch.systemsx.cisd.openbis.dss.client.api.v1.IDataSetDss; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.NewDataSetMetadataDTO; +import ch.systemsx.cisd.openbis.plugin.screening.client.api.v1.IScreeningOpenbisServiceFacade; +import ch.systemsx.cisd.openbis.plugin.screening.client.api.v1.ScreeningOpenbisServiceFacade.IImageOutputStreamProvider; +import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ExperimentIdentifier; +import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ImageDatasetMetadata; +import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ImageDatasetReference; +import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.Plate; +import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.PlateImageReference; +import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.WellIdentifier; +import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.WellPosition; + +/** + * + * + * @author Franz-Josef Elmer + */ +public class OpenBISScreeningMLTest extends AbstractFileSystemTestCase +{ + private static final FilenameFilter FILTER_TEMP_DIR = new FilenameFilter() + { + public boolean accept(File dir, String name) + { + return name.startsWith(OpenBISScreeningML.TEMP_DIR_PREFIX) + && name.endsWith(OpenBISScreeningML.TEMP_DIR_POSTFIX); + } + }; + + private Mockery context; + private IScreeningOpenbisServiceFacade openbis; + + private File tempDir; + + private ExperimentIdentifier eId1; + + private ExperimentIdentifier eId2; + + private IDataSetDss ds1; + + private IDataSetDss ds2; + + @BeforeMethod + public void beforeMethod() + { + context = new Mockery(); + openbis = context.mock(IScreeningOpenbisServiceFacade.class); + ds1 = context.mock(IDataSetDss.class, "ds1"); + ds2 = context.mock(IDataSetDss.class, "ds2"); + FileUtilities.deleteRecursively(workingDirectory); + workingDirectory.mkdirs(); + OpenBISScreeningML.tempDir = workingDirectory; + eId1 = new ExperimentIdentifier("E1", "P", "S", "e-1"); + eId2 = new ExperimentIdentifier("E2", "P", "S", "e-2"); + context.checking(new Expectations() + { + { + one(openbis).listExperiments(); + will(returnValue(Arrays.asList(eId1, eId2))); + + one(openbis).listPlates(); + Plate p1 = new Plate("PLATE-1", "S", "s-1", eId1); + Plate p2 = new Plate("PLATE-2", "S", "s-2", eId2); + will(returnValue(Arrays.asList(p1, p2))); + } + }); + OpenBISScreeningML.init(openbis); + tempDir = OpenBISScreeningML.tempDir.listFiles(FILTER_TEMP_DIR)[0]; + } + + @AfterMethod + public void afterMethod() + { + context.assertIsSatisfied(); + } + + @Test + public void testLogout() + { + context.checking(new Expectations() + { + { + one(openbis).logout(); + } + }); + File a = new File(tempDir, "a"); + a.mkdirs(); + FileUtilities.writeToFile(new File(a, "1.txt"), "one"); + FileUtilities.writeToFile(new File(tempDir, "2.txt"), "two"); + + OpenBISScreeningML.logout(); + + assertEquals(false, tempDir.exists()); + context.assertIsSatisfied(); + } + + @Test + public void testListExperiments() + { + Object[][] experiments = OpenBISScreeningML.listExperiments(); + + sort(experiments); + assertEquals("/S/P/E1", experiments[0][0]); + assertEquals("e-1", experiments[0][1]); + assertEquals("S", experiments[0][2]); + assertEquals("P", experiments[0][3]); + assertEquals("E1", experiments[0][4]); + assertEquals("/S/P/E2", experiments[1][0]); + assertEquals("e-2", experiments[1][1]); + assertEquals("S", experiments[1][2]); + assertEquals("P", experiments[1][3]); + assertEquals("E2", experiments[1][4]); + assertEquals(2, experiments.length); + context.assertIsSatisfied(); + } + + @Test + public void testListPlates() + { + Object[][] plates = OpenBISScreeningML.listPlates(); + + sort(plates); + assertEquals("/S/PLATE-1", plates[0][0]); + assertEquals("s-1", plates[0][1]); + assertEquals("S", plates[0][2]); + assertEquals("PLATE-1", plates[0][3]); + assertEquals("/S/P/E1", plates[0][4]); + assertEquals("e-1", plates[0][5]); + assertEquals("S", plates[0][6]); + assertEquals("P", plates[0][7]); + assertEquals("E1", plates[0][8]); + assertEquals("/S/PLATE-2", plates[1][0]); + assertEquals("s-2", plates[1][1]); + assertEquals("S", plates[1][2]); + assertEquals("PLATE-2", plates[1][3]); + assertEquals("/S/P/E2", plates[1][4]); + assertEquals("e-2", plates[1][5]); + assertEquals("S", plates[1][6]); + assertEquals("P", plates[1][7]); + assertEquals("E2", plates[1][8]); + assertEquals(2, plates.length); + context.assertIsSatisfied(); + } + + @Test + public void testListPlatesByExperiment() + { + try + { + OpenBISScreeningML.listPlates("/S/P/E3"); + fail("RuntimeException expected"); + } catch (RuntimeException ex) + { + assertEquals("No experiment with that code found.", ex.getMessage()); + } + + Object[][] plates = OpenBISScreeningML.listPlates("/S/P/E1"); + + sort(plates); + assertEquals("/S/PLATE-1", plates[0][0]); + assertEquals("s-1", plates[0][1]); + assertEquals("S", plates[0][2]); + assertEquals("PLATE-1", plates[0][3]); + assertEquals("/S/P/E1", plates[0][4]); + assertEquals("e-1", plates[0][5]); + assertEquals("S", plates[0][6]); + assertEquals("P", plates[0][7]); + assertEquals("E1", plates[0][8]); + assertEquals(1, plates.length); + context.assertIsSatisfied(); + } + + @Test + public void testGetWellProperties() + { + context.checking(new Expectations() + { + { + Plate plate1 = new Plate("PLATE-1", "S", "s-1", eId1); + one(openbis).listPlateWells(plate1); + WellIdentifier w1 = new WellIdentifier(plate1, new WellPosition(1, 1), "w1"); + WellIdentifier w2 = new WellIdentifier(plate1, new WellPosition(1, 2), "w2"); + WellIdentifier w3 = new WellIdentifier(plate1, new WellPosition(2, 1), "w3"); + will(returnValue(Arrays.asList(w1, w2, w3))); + + one(openbis).getWellProperties(w2); + Map<String, String> properties = new LinkedHashMap<String, String>(); + properties.put("answer", "42"); + properties.put("name", "Albert"); + will(returnValue(properties)); + } + }); + + Object[][] wellProperties = OpenBISScreeningML.getWellProperties("/S/PLATE-1", 1, 2); + + assertEquals("answer", wellProperties[0][0]); + assertEquals("42", wellProperties[0][1]); + assertEquals("name", wellProperties[1][0]); + assertEquals("Albert", wellProperties[1][1]); + assertEquals(2, wellProperties.length); + context.assertIsSatisfied(); + } + + @Test + public void testUpdateWellProperties() + { + context.checking(new Expectations() + { + { + Plate plate1 = new Plate("PLATE-1", "S", "s-1", eId1); + one(openbis).listPlateWells(plate1); + WellIdentifier w1 = new WellIdentifier(plate1, new WellPosition(1, 1), "w1"); + WellIdentifier w2 = new WellIdentifier(plate1, new WellPosition(1, 2), "w2"); + WellIdentifier w3 = new WellIdentifier(plate1, new WellPosition(2, 1), "w3"); + will(returnValue(Arrays.asList(w1, w2, w3))); + + Map<String, String> properties = new LinkedHashMap<String, String>(); + properties.put("A", "42"); + properties.put("B", "43"); + one(openbis).updateWellProperties(w2, properties); + } + }); + + OpenBISScreeningML.updateWellProperties("/S/PLATE-1", 1, 2, new Object[][] {{"A", "42"}, {"B", "43"}}); + + context.assertIsSatisfied(); + } + + @Test + public void testLoadDataSets() + { + final File dataSetFolder = new File(OpenBISScreeningML.tempDir, OpenBISScreeningML.DATASETS_FOLDER); + final File ds1Folder = new File(dataSetFolder, "ds-1"); + File ds2Folder = new File(dataSetFolder, "ds-2"); + ds2Folder.mkdirs(); + context.checking(new Expectations() + { + { + one(openbis).getDataSets(new Plate("PLATE-1", "S", "s-1", eId1)); + will(returnValue(Arrays.asList(ds1, ds2))); + + one(ds1).getCode(); + will(returnValue("ds-1")); + + one(ds1).getLinkOrCopyOfContents(null, dataSetFolder); + will(returnValue(ds1Folder)); + + one(ds2).getCode(); + will(returnValue("ds-2")); + } + }); + + Object[][] result = OpenBISScreeningML.loadDataSets("/S/PLATE-1"); + + assertEquals("ds-1", result[0][0]); + assertEquals(ds1Folder.getPath(), result[0][1]); + assertEquals("ds-2", result[1][0]); + assertEquals(ds2Folder.getPath(), result[1][1]); + assertEquals(2, result.length); + context.assertIsSatisfied(); + } + + @Test + public void testUpdateDataSet() + { + final File dataSetFolder = new File(OpenBISScreeningML.tempDir, OpenBISScreeningML.DATASETS_FOLDER); + final File ds1Folder = new File(dataSetFolder, "ds-1"); + ds1Folder.mkdirs(); + final RecordingMatcher<NewDataSetMetadataDTO> metaDataMatcher = new RecordingMatcher<NewDataSetMetadataDTO>(); + context.checking(new Expectations() + { + { + Map<String, String> properties = new LinkedHashMap<String, String>(); + properties.put("A", "42"); + properties.put("B", "43"); + try + { + one(openbis).putDataSet(with(new Plate("PLATE-1", "S", "s-1", eId1)), + with(ds1Folder), with(metaDataMatcher)); + will(returnValue(ds1)); + } catch (Exception ex) + { + throw CheckedExceptionTunnel.wrapIfNecessary(ex); + } + + one(ds1).getCode(); + will(returnValue("DS-1")); + } + }); + + Object code = + OpenBISScreeningML.uploadDataSet("/S/PLATE-1", ds1Folder.getPath(), "my-type", + new Object[][] {{"A", "42"}, {"B", "43"}}); + + assertEquals("DS-1", code); + assertEquals("my-type", metaDataMatcher.recordedObject().tryDataSetType()); + assertEquals("{A=42, B=43}", metaDataMatcher.recordedObject().getProperties().toString()); + context.assertIsSatisfied(); + } + + @Test + public void testLoadImages() + { + final RecordingMatcher<List<PlateImageReference>> imgRefsMatcher1 = + new RecordingMatcher<List<PlateImageReference>>(); + final RecordingMatcher<List<PlateImageReference>> imgRefsMatcher2 = + new RecordingMatcher<List<PlateImageReference>>(); + final Sequence sequence = context.sequence("load"); + context.checking(new Expectations() + { + { + Plate plate = new Plate("PLATE-1", "S", "s-1", eId1); + exactly(2).of(openbis).listRawImageDatasets(Arrays.asList(plate)); + ImageDatasetReference ds1Ref = + new ImageDatasetReference("ds1", "", plate, eId1, null, null, null, + null); + List<ImageDatasetReference> imageRefs = Arrays.asList(ds1Ref); + will(returnValue(imageRefs)); + + exactly(2).of(openbis).listImageMetadata(imageRefs); + List<String> channelCodes = Arrays.asList("R", "G"); + List<String> channelLabels = Arrays.asList("red", "green"); + ImageDatasetMetadata metaData1 = + new ImageDatasetMetadata(ds1Ref, channelCodes, channelLabels, 1, 2, + 100, 60, 10, 6); + will(returnValue(Arrays.asList(metaData1))); + + try + { + one(openbis).loadImages(with(imgRefsMatcher1), + with(new BaseMatcher<IImageOutputStreamProvider>() + { + public boolean matches(Object item) + { + if (item instanceof IImageOutputStreamProvider) + { + IImageOutputStreamProvider provider = + (IImageOutputStreamProvider) item; + List<PlateImageReference> recordedObject = + imgRefsMatcher1.recordedObject(); + for (PlateImageReference ref : recordedObject) + { + try + { + OutputStream outputStream = + provider.getOutputStream(ref); + new PrintWriter(outputStream, true) + .println(ref.toString() + " (1)"); + } catch (IOException ex) + { + throw CheckedExceptionTunnel + .wrapIfNecessary(ex); + } + } + return true; + } + return false; + } + + public void describeTo(Description description) + { + } + }), with(false)); + inSequence(sequence); + one(openbis).loadImages(with(imgRefsMatcher2), + with(new BaseMatcher<IImageOutputStreamProvider>() + { + public boolean matches(Object item) + { + if (item instanceof IImageOutputStreamProvider) + { + IImageOutputStreamProvider provider = + (IImageOutputStreamProvider) item; + List<PlateImageReference> recordedObject = + imgRefsMatcher2.recordedObject(); + for (PlateImageReference ref : recordedObject) + { + try + { + OutputStream outputStream = + provider.getOutputStream(ref); + new PrintWriter(outputStream, true) + .println(ref.toString() + " (2)"); + } catch (IOException ex) + { + throw CheckedExceptionTunnel + .wrapIfNecessary(ex); + } + } + return true; + } + return false; + } + + public void describeTo(Description description) + { + } + }), with(false)); + inSequence(sequence); + } catch (IOException ex) + { + throw CheckedExceptionTunnel.wrapIfNecessary(ex); + } + } + }); + + Object[][][] result1 = OpenBISScreeningML.loadImages("/S/PLATE-1", 1, 2, 1, new String[] {"G"}); + List<PlateImageReference> imgRefs1 = imgRefsMatcher1.recordedObject(); + for (PlateImageReference plateImageReference : imgRefs1) + { + assertEquals("ds1", plateImageReference.getDatasetCode()); + assertEquals(1, plateImageReference.getWellPosition().getWellRow()); + assertEquals(2, plateImageReference.getWellPosition().getWellColumn()); + } + assertEquals("G", imgRefs1.get(0).getChannel()); + assertEquals(1, imgRefs1.get(0).getTile()); + assertEquals(1, imgRefs1.size()); + assertEquals(2, result1.length); + assertEquals("/images/img_PLATE-1_ds1_row1_col2_G_tile1.tiff", getImagePath(result1, 0)); + assertEquals("Image for [dataset ds1, well [1, 2], channel G, tile 1] (1)", FileUtilities + .loadToString(new File(result1[0][0][0].toString())).trim()); + assertEquals(1, result1[0].length); + assertEquals( + "[G, 1, PLATE-1:A2, /S/PLATE-1, s-1, S, PLATE-1, 1, 2, /S/P/E1, e-1, S, P, E1, ds1]", + Arrays.asList(result1[1][0]).toString()); + assertEquals(1, result1[1].length); + + Object[][][] result2 = OpenBISScreeningML.loadImages("/S/PLATE-1", 1, 2); + List<PlateImageReference> imgRefs2 = imgRefsMatcher2.recordedObject(); + for (PlateImageReference plateImageReference : imgRefs2) + { + assertEquals("ds1", plateImageReference.getDatasetCode()); + assertEquals(1, plateImageReference.getWellPosition().getWellRow()); + assertEquals(2, plateImageReference.getWellPosition().getWellColumn()); + } + assertEquals("R", imgRefs2.get(0).getChannel()); + assertEquals(0, imgRefs2.get(0).getTile()); + assertEquals("R", imgRefs2.get(1).getChannel()); + assertEquals(1, imgRefs2.get(1).getTile()); + assertEquals("G", imgRefs2.get(2).getChannel()); + assertEquals(0, imgRefs2.get(2).getTile()); + assertEquals(3, imgRefs2.size()); + + assertEquals(2, result2.length); + assertEquals("/images/img_PLATE-1_ds1_row1_col2_R_tile0.tiff", getImagePath(result2, 0)); + assertEquals("Image for [dataset ds1, well [1, 2], channel R, tile 0] (2)", FileUtilities + .loadToString(new File(result2[0][0][0].toString())).trim()); + assertEquals("/images/img_PLATE-1_ds1_row1_col2_R_tile1.tiff", getImagePath(result2, 1)); + assertEquals("Image for [dataset ds1, well [1, 2], channel R, tile 1] (2)", FileUtilities + .loadToString(new File(result2[0][1][0].toString())).trim()); + assertEquals("/images/img_PLATE-1_ds1_row1_col2_G_tile0.tiff", getImagePath(result2, 2)); + assertEquals("Image for [dataset ds1, well [1, 2], channel G, tile 0] (2)", FileUtilities + .loadToString(new File(result2[0][2][0].toString())).trim()); + assertEquals("/images/img_PLATE-1_ds1_row1_col2_G_tile1.tiff", getImagePath(result2, 3)); + assertEquals("Image for [dataset ds1, well [1, 2], channel G, tile 1] (1)", FileUtilities + .loadToString(new File(result2[0][3][0].toString())).trim()); + assertEquals(4, result2[0].length); + assertEquals( + "[R, 0, PLATE-1:A2, /S/PLATE-1, s-1, S, PLATE-1, 1, 2, /S/P/E1, e-1, S, P, E1, ds1]", + Arrays.asList(result2[1][0]).toString()); + assertEquals( + "[R, 1, PLATE-1:A2, /S/PLATE-1, s-1, S, PLATE-1, 1, 2, /S/P/E1, e-1, S, P, E1, ds1]", + Arrays.asList(result2[1][1]).toString()); + assertEquals( + "[G, 0, PLATE-1:A2, /S/PLATE-1, s-1, S, PLATE-1, 1, 2, /S/P/E1, e-1, S, P, E1, ds1]", + Arrays.asList(result2[1][2]).toString()); + assertEquals( + "[G, 1, PLATE-1:A2, /S/PLATE-1, s-1, S, PLATE-1, 1, 2, /S/P/E1, e-1, S, P, E1, ds1]", + Arrays.asList(result2[1][3]).toString()); + assertEquals(4, result2[1].length); + context.assertIsSatisfied(); + } + + private String getImagePath(Object[][][] result, int i) + { + return result[0][i][0].toString() + .substring(tempDir.getPath().length()); + } + + private void sort(Object[][] entities) + { + Arrays.sort(entities, new Comparator<Object[]>() + { + public int compare(Object[] o1, Object[] o2) + { + return o1[0].toString().compareTo(o2[0].toString()); + } + }); + } + +} diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/ScreeningOpenbisServiceFacadeTest.java b/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/ScreeningOpenbisServiceFacadeTest.java index a734609c0dfe06c12605529e7ce1e293bff3f13c..e1f185bec004a07be15716e71206937ffec9b783 100644 --- a/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/ScreeningOpenbisServiceFacadeTest.java +++ b/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/ScreeningOpenbisServiceFacadeTest.java @@ -37,6 +37,7 @@ import ch.systemsx.cisd.common.io.IContent; import ch.systemsx.cisd.openbis.dss.client.api.v1.IDssComponent; import ch.systemsx.cisd.openbis.dss.screening.server.DssServiceRpcScreening; import ch.systemsx.cisd.openbis.dss.screening.shared.api.v1.IDssServiceRpcScreening; +import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationChangingService; import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationService; import ch.systemsx.cisd.openbis.plugin.screening.client.api.v1.ScreeningOpenbisServiceFacade.IImageOutputStreamProvider; import ch.systemsx.cisd.openbis.plugin.screening.server.ScreeningServer; @@ -118,12 +119,15 @@ public class ScreeningOpenbisServiceFacadeTest extends AssertJUnit private IImageTransformerFactory transformerFactory; + private IGeneralInformationChangingService generalInformationChangingService; + @BeforeMethod public void beforeMethod() { context = new Mockery(); screeningService = context.mock(IScreeningApiServer.class); generalInformationService = context.mock(IGeneralInformationService.class); + generalInformationChangingService = context.mock(IGeneralInformationChangingService.class); dssComponent = context.mock(IDssComponent.class); dssServiceFactory = context.mock(IDssServiceFactory.class); i1id = new ImageDatasetReference(DATA_SET1, URL1, null, null, null, null, null, null); @@ -170,7 +174,7 @@ public class ScreeningOpenbisServiceFacadeTest extends AssertJUnit facade = new ScreeningOpenbisServiceFacade(SESSION_TOKEN, screeningService, ScreeningServer.MINOR_VERSION, dssServiceFactory, dssComponent, - generalInformationService); + generalInformationService, generalInformationChangingService); } @AfterMethod diff --git a/screening/sourceTest/java/tests.xml b/screening/sourceTest/java/tests.xml index f94a4e51e6a67b419f812d793786684c87708c5c..a51e0e7f7a657316b2e08f141241ca0a1daa6e52 100644 --- a/screening/sourceTest/java/tests.xml +++ b/screening/sourceTest/java/tests.xml @@ -9,5 +9,8 @@ <package name="ch.systemsx.cisd.openbis.plugin.screening.*" /> <package name="ch.systemsx.cisd.openbis.dss.*" /> </packages> + <classes> + <class name="OpenBISScreeningMLTest"/> + </classes> </test> </suite> diff --git a/screening/sourceTest/java/tests_fast.xml b/screening/sourceTest/java/tests_fast.xml index e85dda9499724b398faca07d2646e9de8d415df9..6a5f4e0060c4026b1c586020cf584722f2c42db2 100644 --- a/screening/sourceTest/java/tests_fast.xml +++ b/screening/sourceTest/java/tests_fast.xml @@ -11,6 +11,9 @@ <packages> <package name="ch.systemsx.cisd.openbis.plugin.screening.*" /> <package name="ch.systemsx.cisd.openbis.dss.*" /> - </packages> + </packages> + <classes> + <class name="OpenBISScreeningMLTest"/> + </classes> </test> </suite>