diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/resolver/ExperimentFolderResolver.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/resolver/ExperimentFolderResolver.java index 0e1082dce6afd80775b6fc37fc05ab3c1f5132f9..309b993dfcb98c2e7a43fca499f5993b52c9f579 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/resolver/ExperimentFolderResolver.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/resolver/ExperimentFolderResolver.java @@ -27,6 +27,7 @@ import ch.systemsx.cisd.openbis.dss.generic.server.ftp.FtpPathResolverContext; import ch.systemsx.cisd.openbis.dss.generic.server.ftp.IFtpPathResolver; import ch.systemsx.cisd.openbis.generic.shared.IETLLIMSService; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment; +import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentFetchOptions; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifierFactory; @@ -76,13 +77,16 @@ public class ExperimentFolderResolver implements IFtpPathResolver ExperimentIdentifier identifier = new ExperimentIdentifierFactory(expIdentifier).createIdentifier(); - Experiment exp = service.tryToGetExperiment(sessionToken, identifier); - if (exp == null) + List<Experiment> experiments = + service.listExperiments(sessionToken, Collections.singletonList(identifier), + new ExperimentFetchOptions()); + if (experiments == null || experiments.isEmpty()) { return Collections.emptyList(); } else { - return childLister.listExperimentChildrenPaths(exp, expIdentifier, context); + return childLister.listExperimentChildrenPaths(experiments.get(0), expIdentifier, + context); } } } diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/resolver/ProjectFolderResolver.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/resolver/ProjectFolderResolver.java index 89e5903264c5a952443c8b04f3d6429e432c294e..b3215a57a93aad6e81fa2e4ac6ee740956538eed 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/resolver/ProjectFolderResolver.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/resolver/ProjectFolderResolver.java @@ -17,6 +17,7 @@ package ch.systemsx.cisd.openbis.dss.generic.server.ftp.resolver; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import org.apache.commons.lang.StringUtils; @@ -27,6 +28,7 @@ import ch.systemsx.cisd.openbis.dss.generic.server.ftp.FtpPathResolverContext; import ch.systemsx.cisd.openbis.dss.generic.server.ftp.IFtpPathResolver; import ch.systemsx.cisd.openbis.generic.shared.IETLLIMSService; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment; +import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentFetchOptions; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifierFactory; @@ -80,6 +82,7 @@ public class ProjectFolderResolver implements IFtpPathResolver String sessionToken = context.getSessionToken(); ProjectIdentifier identifier = new ProjectIdentifierFactory(projectIdentifier).createIdentifier(); - return service.listExperiments(sessionToken, identifier); + return service.listExperimentsForProjects(sessionToken, + Collections.singletonList(identifier), new ExperimentFetchOptions()); } } diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/resolver/TemplateBasedDataSetResourceResolver.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/resolver/TemplateBasedDataSetResourceResolver.java index 692e4fdb44a8cafa50814d641e04733a87f74d7f..321e810a5b0ec5b606e302f279c2323e1891d8a2 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/resolver/TemplateBasedDataSetResourceResolver.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/resolver/TemplateBasedDataSetResourceResolver.java @@ -54,6 +54,7 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSet; 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.ExternalData; +import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentFetchOptions; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifierFactory; @@ -408,16 +409,25 @@ public class TemplateBasedDataSetResourceResolver implements IFtpPathResolver, ExperimentIdentifier experimentIdentifier = new ExperimentIdentifierFactory(experimentId).createIdentifier(); - Experiment result = null; + List<Experiment> result = null; try { - result = service.tryToGetExperiment(sessionToken, experimentIdentifier); + result = + service.listExperiments(sessionToken, + Collections.singletonList(experimentIdentifier), + new ExperimentFetchOptions()); } catch (Throwable t) { operationLog.warn("Failed to get experiment with identifier :" + experimentId, t); } - return result; + if (result == null || result.isEmpty()) + { + return null; + } else + { + return result.get(0); + } } private String extractExperimentIdFromPath(String path) @@ -467,8 +477,8 @@ public class TemplateBasedDataSetResourceResolver implements IFtpPathResolver, FtpFile childFtpFile = FtpFileFactory.createFtpFile(dataSetCode, childPath, - evalElement.contentNode, getContentProvider.asContent(evalElement.dataSet), - fileFilter); + evalElement.contentNode, + getContentProvider.asContent(evalElement.dataSet), fileFilter); result.add(childFtpFile); } } diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/resolver/TemplateBasedDataSetResourceResolverTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/resolver/TemplateBasedDataSetResourceResolverTest.java index dd0c5c39882cd6e893bbab5c7ef877ba0dc0dd88..1cf0010b2b02ba496f589f414ef6f93f035a5d43 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/resolver/TemplateBasedDataSetResourceResolverTest.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/ftp/resolver/TemplateBasedDataSetResourceResolverTest.java @@ -23,6 +23,7 @@ import java.io.InputStream; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Date; import java.util.EnumSet; import java.util.List; @@ -58,13 +59,14 @@ 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.IDatasetLocation; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.DataSetBuilder; +import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentFetchOptions; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifierFactory; /** * @author Kaloyan Enimanev */ -@Friend(toClasses=TemplateBasedDataSetResourceResolver.class) +@Friend(toClasses = TemplateBasedDataSetResourceResolver.class) public class TemplateBasedDataSetResourceResolverTest extends AbstractFileSystemTestCase { private static final class SimpleFileContentProvider implements IHierarchicalContentProvider @@ -75,7 +77,7 @@ public class TemplateBasedDataSetResourceResolverTest extends AbstractFileSystem { this.root = root; } - + public IHierarchicalContent asContent(ExternalData dataSet) { return asContent((IDatasetLocation) dataSet.tryGetAsDataSet()); @@ -98,9 +100,9 @@ public class TemplateBasedDataSetResourceResolverTest extends AbstractFileSystem datasetDirectory, IDelegatedAction.DO_NOTHING); } } - + private static final Date REGISTRATION_DATE = new Date(42); - + private static final String RENDERED_REGISTRATION_DATE = TemplateBasedDataSetResourceResolver .extractDateValue(REGISTRATION_DATE); @@ -123,14 +125,15 @@ public class TemplateBasedDataSetResourceResolverTest extends AbstractFileSystem private static final String BIG_TEMPLATE = "DS-${dataSetType}-${dataSetCode}-${dataSetDate}-${disambiguation}"; - private TrackingMockery context; + private IETLLIMSService service; private IHierarchicalContentProvider hierarchicalContentProvider; private FtpPathResolverContext resolverContext; + private TemplateBasedDataSetResourceResolver resolver; private Experiment experiment; @@ -161,19 +164,21 @@ public class TemplateBasedDataSetResourceResolverTest extends AbstractFileSystem File root = new File(workingDirectory, "data-sets"); root.mkdirs(); simpleFileContentProvider = new SimpleFileContentProvider(root); - - resolverContext = new FtpPathResolverContext(SESSION_TOKEN, service, generalInfoService, null); + resolverContext = + new FtpPathResolverContext(SESSION_TOKEN, service, generalInfoService, null); context.checking(new Expectations() { { ExperimentIdentifier experimentIdentifier = new ExperimentIdentifierFactory(EXP_ID).createIdentifier(); - allowing(service).tryToGetExperiment(SESSION_TOKEN, experimentIdentifier); + allowing(service).listExperiments(SESSION_TOKEN, + Collections.singletonList(experimentIdentifier), + new ExperimentFetchOptions()); will(returnValue(experiment)); } }); - + ds1 = new DataSetBuilder().experiment(experiment).code("ds1").type(DS_TYPE1) .registrationDate(REGISTRATION_DATE).getDataSet(); @@ -208,71 +213,75 @@ public class TemplateBasedDataSetResourceResolverTest extends AbstractFileSystem throw new Error(m.getName() + "() : ", t); } } - + @Test public void testInvalidConfig() { FtpServerConfig config = - new FtpServerConfigBuilder().withTemplate(TEMPLATE_WITH_FILENAMES).showParentsAndChildren().getConfig(); + new FtpServerConfigBuilder().withTemplate(TEMPLATE_WITH_FILENAMES) + .showParentsAndChildren().getConfig(); try { new TemplateBasedDataSetResourceResolver(config); fail("ConfigurationFailureException expected"); } catch (ConfigurationFailureException ex) { - assertEquals("Template contains file name variable and the flag " + - "to show parents/children data sets is set.", ex.getMessage()); + assertEquals("Template contains file name variable and the flag " + + "to show parents/children data sets is set.", ex.getMessage()); } } - + @Test public void testWithParentsTopLevel() { FtpServerConfig config = - new FtpServerConfigBuilder().withTemplate(BIG_TEMPLATE).showParentsAndChildren().getConfig(); + new FtpServerConfigBuilder().withTemplate(BIG_TEMPLATE).showParentsAndChildren() + .getConfig(); resolver = new TemplateBasedDataSetResourceResolver(config); resolver.setContentProvider(simpleFileContentProvider); - - ds1.setParents(Arrays.<ExternalData>asList(ds2)); - final List<ExternalData> dataSets = Arrays.<ExternalData>asList(ds1); - + + ds1.setParents(Arrays.<ExternalData> asList(ds2)); + final List<ExternalData> dataSets = Arrays.<ExternalData> asList(ds1); + prepareExperimentListExpectations(dataSets); prepareGetDataSetMetaData(ds1); prepareListDataSetsByCode(ds2); - + String dataSetPathElement = "DS-DS_TYPE1-ds1-" + RENDERED_REGISTRATION_DATE + "-A"; String path = EXP_ID + FtpConstants.FILE_SEPARATOR + dataSetPathElement; FtpFile ftpFile = resolver.resolve(path, resolverContext); - + assertEquals(dataSetPathElement, ftpFile.getName()); assertEquals(path, ftpFile.getAbsolutePath()); assertEquals(true, ftpFile.isDirectory()); List<FtpFile> files = ftpFile.listFiles(); - assertEquals("PARENT-DS-DS_TYPE2-ds2-" + RENDERED_REGISTRATION_DATE + "-A", files.get(0).getName()); + assertEquals("PARENT-DS-DS_TYPE2-ds2-" + RENDERED_REGISTRATION_DATE + "-A", files.get(0) + .getName()); assertEquals(true, files.get(0).isDirectory()); assertEquals("original", files.get(1).getName()); assertEquals(true, files.get(1).isDirectory()); assertEquals(2, files.size()); } - + @Test public void testChildOfParent() { FtpServerConfig config = - new FtpServerConfigBuilder().withTemplate(BIG_TEMPLATE).showParentsAndChildren().getConfig(); + new FtpServerConfigBuilder().withTemplate(BIG_TEMPLATE).showParentsAndChildren() + .getConfig(); resolver = new TemplateBasedDataSetResourceResolver(config); resolver.setContentProvider(simpleFileContentProvider); - - ds1.setParents(Arrays.<ExternalData>asList(ds2)); + + ds1.setParents(Arrays.<ExternalData> asList(ds2)); ds2.setChildren(Arrays.<ExternalData> asList(ds1, ds3)); - final List<ExternalData> dataSets = Arrays.<ExternalData>asList(ds1); - + final List<ExternalData> dataSets = Arrays.<ExternalData> asList(ds1); + prepareExperimentListExpectations(dataSets); prepareGetDataSetMetaData(ds1); prepareListDataSetsByCode(ds2); prepareGetDataSetMetaData(ds2); prepareListDataSetsByCode(ds1, ds3); - + String dataSetPathElement = "DS-DS_TYPE1-ds1-" + RENDERED_REGISTRATION_DATE + "-A"; String ds2AsParent = "PARENT-DS-DS_TYPE2-ds2-" + RENDERED_REGISTRATION_DATE + "-A"; @@ -280,7 +289,7 @@ public class TemplateBasedDataSetResourceResolverTest extends AbstractFileSystem EXP_ID + FtpConstants.FILE_SEPARATOR + dataSetPathElement + FtpConstants.FILE_SEPARATOR + ds2AsParent; FtpFile ftpFile = resolver.resolve(path, resolverContext); - + assertEquals(ds2AsParent, ftpFile.getName()); assertEquals(path, ftpFile.getAbsolutePath()); assertEquals(true, ftpFile.isDirectory()); @@ -292,7 +301,7 @@ public class TemplateBasedDataSetResourceResolverTest extends AbstractFileSystem assertEquals(true, files.get(1).isDirectory()); assertEquals(2, files.size()); } - + @Test public void testAvoidInfiniteParentChildChains() { @@ -377,51 +386,52 @@ public class TemplateBasedDataSetResourceResolverTest extends AbstractFileSystem EXP_ID + FtpConstants.FILE_SEPARATOR + ds1.getCode() + FtpConstants.FILE_SEPARATOR + subPath; - List<ExternalData> dataSets = Arrays.<ExternalData>asList(ds1); + List<ExternalData> dataSets = Arrays.<ExternalData> asList(ds1); prepareExperimentListExpectations(dataSets); context.checking(new Expectations() { { - IHierarchicalContent content = context.mock(IHierarchicalContent.class, ds1.getCode()); + IHierarchicalContent content = + context.mock(IHierarchicalContent.class, ds1.getCode()); one(hierarchicalContentProvider).asContent((ExternalData) ds1); will(returnValue(content)); - + IHierarchicalContentNode rootNode = context.mock(IHierarchicalContentNode.class, "root"); IHierarchicalContentNode fileNode = context.mock(IHierarchicalContentNode.class, "file"); - + one(content).getRootNode(); will(returnValue(rootNode)); - + one(rootNode).getChildNodes(); will(returnValue(Arrays.asList(fileNode))); - + one(fileNode).getName(); will(returnValue(subPath)); - + one(fileNode).getRelativePath(); will(returnValue(subPath)); - + exactly(2).of(fileNode).isDirectory(); will(returnValue(false)); - + one(fileNode).getFileLength(); will(returnValue(2L)); - + one(fileNode).getFile(); will(returnValue(null)); - + one(fileNode).getInputStream(); ByteArrayInputStream is = new ByteArrayInputStream(new byte[] {}); will(returnValue(is)); - + allowing(content).getNode(subPath); will(returnValue(fileNode)); - + atLeast(1).of(content).close(); } }); @@ -446,8 +456,7 @@ public class TemplateBasedDataSetResourceResolverTest extends AbstractFileSystem resolver = new TemplateBasedDataSetResourceResolver(config); resolver.setContentProvider(simpleFileContentProvider); - List<ExternalData> dataSets = - Arrays.<ExternalData>asList(ds1, ds2); + List<ExternalData> dataSets = Arrays.<ExternalData> asList(ds1, ds2); prepareExperimentListExpectations(dataSets); @@ -463,14 +472,12 @@ public class TemplateBasedDataSetResourceResolverTest extends AbstractFileSystem assertEquals(2, files.size()); } - private void prepareExperimentListExpectations(final List<ExternalData> dataSets) { context.checking(new Expectations() { { - one(service).listDataSetsByExperimentID(SESSION_TOKEN, - new TechId(experiment)); + one(service).listDataSetsByExperimentID(SESSION_TOKEN, new TechId(experiment)); will(returnValue(dataSets)); } }); @@ -495,15 +502,15 @@ public class TemplateBasedDataSetResourceResolverTest extends AbstractFileSystem { final List<String> codes = extractCodes(dataSets); context.checking(new Expectations() - { { - one(service).listDataSetsByCode(SESSION_TOKEN, codes); - will(returnValue(Arrays.asList(dataSets))); - } - }); - + { + one(service).listDataSetsByCode(SESSION_TOKEN, codes); + will(returnValue(Arrays.asList(dataSets))); + } + }); + } - + private List<String> extractCodes(final ExternalData... dataSets) { final List<String> codes = new ArrayList<String>(); @@ -513,7 +520,7 @@ public class TemplateBasedDataSetResourceResolverTest extends AbstractFileSystem } return codes; } - + private String getHierarchicalContentMockName(String dataSetCode) { return dataSetCode; diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServer.java index e38667f95d51bc3ecbc3e87f292eaa8af1e2e0d2..4fe150eddeae782aa60d7272015ff923347aca7c 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServer.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServer.java @@ -637,6 +637,12 @@ public abstract class AbstractServer<T> extends AbstractServiceWithLogger<T> imp session.setBaseIndexURL(baseIndexURL); } + public String getBaseIndexURL(String sessionToken) + { + final Session session = getSessionManager().getSession(sessionToken); + return session.getBaseIndexURL(); + } + public List<GridCustomColumn> listGridCustomColumns(String sessionToken, String gridId) { Session session = getSession(sessionToken); 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 536e4538a85295121936a9a499c0b5f8b0e5d036..16c1aa7afa42166ec9c8146b1d449a201f380f24 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 @@ -50,6 +50,7 @@ import ch.systemsx.cisd.openbis.generic.server.business.bo.IRoleAssignmentTable; 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.datasetlister.IDatasetLister; +import ch.systemsx.cisd.openbis.generic.server.business.bo.experimentlister.ExperimentLister; 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.server.dataaccess.IDAOFactory; @@ -116,6 +117,8 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE; import ch.systemsx.cisd.openbis.generic.shared.dto.DatastoreServiceDescriptions; import ch.systemsx.cisd.openbis.generic.shared.dto.EntityCollectionForCreationOrUpdate; import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePE; +import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentFetchOption; +import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentFetchOptions; 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.ExternalDataPE; @@ -372,6 +375,92 @@ public class ETLService extends AbstractCommonServer<IETLLIMSService> implements return daoFactory.getCodeSequenceDAO().getNextCodeSequenceId(); } + public List<Experiment> listExperiments(String sessionToken, + List<ExperimentIdentifier> experimentIdentifiers, + ExperimentFetchOptions experimentFetchOptions) throws UserFailureException + { + if (sessionToken == null) + { + throw new IllegalArgumentException("SessionToken was null"); + } + if (experimentIdentifiers == null) + { + throw new IllegalArgumentException("ExperimentIdentifiers were null"); + } + if (experimentFetchOptions == null) + { + throw new IllegalArgumentException("ExperimentFetchOptions were null"); + } + + if (experimentFetchOptions.containsOnlyOption(ExperimentFetchOption.BASIC)) + { + ExperimentLister lister = + new ExperimentLister(daoFactory, getSession(sessionToken).getBaseIndexURL()); + return lister.listExperiments(experimentIdentifiers, experimentFetchOptions); + } else + { + List<Experiment> experiments = new ArrayList<Experiment>(); + for (ExperimentIdentifier experimentIdentifier : experimentIdentifiers) + { + Experiment experiment = tryToGetExperiment(sessionToken, experimentIdentifier); + if (experiment != null) + { + experiment.setFetchOptions(new ExperimentFetchOptions(ExperimentFetchOption + .values())); + experiments.add(experiment); + } + } + return experiments; + } + } + + public List<Experiment> listExperimentsForProjects(String sessionToken, + List<ProjectIdentifier> projectIdentifiers, + ExperimentFetchOptions experimentFetchOptions) + { + if (sessionToken == null) + { + throw new IllegalArgumentException("SessionToken was null"); + } + if (projectIdentifiers == null) + { + throw new IllegalArgumentException("ProjectIdentifiers were null"); + } + if (experimentFetchOptions == null) + { + throw new IllegalArgumentException("ExperimentFetchOptions were null"); + } + + if (experimentFetchOptions.containsOnlyOption(ExperimentFetchOption.BASIC)) + { + ExperimentLister lister = + new ExperimentLister(daoFactory, getSession(sessionToken).getBaseIndexURL()); + return lister.listExperimentsForProjects(projectIdentifiers, experimentFetchOptions); + } else + { + List<Experiment> experiments = new ArrayList<Experiment>(); + for (ProjectIdentifier projectIdentifier : projectIdentifiers) + { + List<Experiment> projectExperiments = + listExperiments(sessionToken, projectIdentifier); + if (projectExperiments != null) + { + for (Experiment projectExperiment : projectExperiments) + { + if (projectExperiment != null) + { + projectExperiment.setFetchOptions(new ExperimentFetchOptions( + ExperimentFetchOption.values())); + experiments.add(projectExperiment); + } + } + + } + } + return experiments; + } + } + public Experiment tryToGetExperiment(String sessionToken, ExperimentIdentifier experimentIdentifier) throws UserFailureException { 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 5a660f9548ac97773c39b86c12c1f03aa88dd051..32f812f42ffc6fbd5aa82ee8a45a63e2aedb46e5 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 @@ -60,6 +60,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetUpdatesDTO; import ch.systemsx.cisd.openbis.generic.shared.dto.DataStoreServerInfo; import ch.systemsx.cisd.openbis.generic.shared.dto.DatastoreServiceDescriptions; import ch.systemsx.cisd.openbis.generic.shared.dto.EntityCollectionForCreationOrUpdate; +import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentFetchOptions; import ch.systemsx.cisd.openbis.generic.shared.dto.ListSamplesByPropertyCriteria; import ch.systemsx.cisd.openbis.generic.shared.dto.NewExternalData; import ch.systemsx.cisd.openbis.generic.shared.dto.NewProperty; @@ -478,6 +479,26 @@ public class ETLServiceLogger extends AbstractServerLogger implements IETLLIMSSe return null; } + public List<Experiment> listExperiments(String sessionToken, + List<ExperimentIdentifier> experimentIdentifiers, + ExperimentFetchOptions experimentFetchOptions) + { + logAccess(sessionToken, "listExperiments", + "EXPERIMENT_IDENTIFIERS(%s), EXPERIMENT_FETCH_OPTIONS(%s)", experimentIdentifiers, + experimentFetchOptions); + return null; + } + + public List<Experiment> listExperimentsForProjects(String sessionToken, + List<ProjectIdentifier> projectIdentifiers, + ExperimentFetchOptions experimentFetchOptions) + { + logAccess(sessionToken, "listExperimentsForProjects", + "PROJECT_IDENTIFIERS(%s), EXPERIMENT_FETCH_OPTIONS(%s)", projectIdentifiers, + experimentFetchOptions); + return null; + } + public List<Project> listProjects(String sessionToken) { logAccess(sessionToken, "listProjects"); diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/experimentlister/ExperimentLister.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/experimentlister/ExperimentLister.java new file mode 100644 index 0000000000000000000000000000000000000000..f6d90b32e30d7f639994be3f4541cec13e36f4b1 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/experimentlister/ExperimentLister.java @@ -0,0 +1,388 @@ +/* + * Copyright 2012 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.experimentlister; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +import net.lemnik.eodsql.DataIterator; +import net.lemnik.eodsql.QueryTool; + +import org.apache.commons.lang.StringUtils; + +import ch.systemsx.cisd.openbis.generic.server.business.bo.common.DatabaseContextUtils; +import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory; +import ch.systemsx.cisd.openbis.generic.shared.basic.PermlinkUtilities; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseInstance; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentType; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space; +import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentFetchOption; +import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentFetchOptions; +import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.DatabaseInstanceIdentifier; +import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier; +import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier; +import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SpaceIdentifier; + +/** + * @author pkupczyk + */ +public class ExperimentLister implements IExperimentLister +{ + + private IDAOFactory daoFactory; + + private String baseIndexURL; + + private IExperimentListingQuery query; + + public ExperimentLister(IDAOFactory daoFactory, String baseIndexURL) + { + this(daoFactory, QueryTool.getQuery(DatabaseContextUtils.getConnection(daoFactory), + IExperimentListingQuery.class), baseIndexURL); + } + + public ExperimentLister(IDAOFactory daoFactory, IExperimentListingQuery query, + String baseIndexURL) + { + if (daoFactory == null) + { + throw new IllegalArgumentException("DaoFactory was null"); + } + if (baseIndexURL == null) + { + throw new IllegalArgumentException("BaseIndexURL was null"); + } + if (query == null) + { + throw new IllegalArgumentException("Query was null"); + } + this.daoFactory = daoFactory; + this.baseIndexURL = baseIndexURL; + this.query = query; + } + + public List<Experiment> listExperiments(List<ExperimentIdentifier> experimentIdentifiers, + ExperimentFetchOptions experimentFetchOptions) + { + if (experimentIdentifiers == null) + { + throw new IllegalArgumentException("ExperimentIdentifiers were null"); + } + if (experimentFetchOptions == null) + { + throw new IllegalArgumentException("ExperimentFetchOptions were null"); + } + if (!experimentFetchOptions.containsOnlyOption(ExperimentFetchOption.BASIC)) + { + throw new IllegalArgumentException( + "Currently only ExperimentFetchOption.BASIC is supported by this method"); + } + + ExperimentIdentifiers identifiers = new ExperimentIdentifiers(experimentIdentifiers); + + DataIterator<ExperimentRecord> iterator = + query.listExperiments(identifiers.getDatabaseInstanceCodes(), + identifiers.getSpaceCodes(), identifiers.getProjectCodes(), + identifiers.getExperimentCodes()); + + return handleResults(iterator, identifiers); + } + + public List<Experiment> listExperimentsForProjects(List<ProjectIdentifier> projectIdentifiers, + ExperimentFetchOptions experimentFetchOptions) + { + if (projectIdentifiers == null) + { + throw new IllegalArgumentException("ProjectIdentifiers were null"); + } + if (experimentFetchOptions == null) + { + throw new IllegalArgumentException("ExperimentFetchOptions were null"); + } + if (!experimentFetchOptions.containsOnlyOption(ExperimentFetchOption.BASIC)) + { + throw new IllegalArgumentException( + "Currently only ExperimentFetchOption.BASIC is supported by this method"); + } + + ProjectIdentifiers identifiers = new ProjectIdentifiers(projectIdentifiers); + + DataIterator<ExperimentRecord> iterator = + query.listExperimentsForProjects(identifiers.getDatabaseInstanceCodes(), + identifiers.getSpaceCodes(), identifiers.getProjectCodes()); + + return handleResults(iterator, identifiers); + } + + private List<Experiment> handleResults(DataIterator<ExperimentRecord> iterator, + ProjectIdentifiers identifiers) + { + if (iterator != null) + { + List<ExperimentRecord> results = new LinkedList<ExperimentRecord>(); + while (iterator.hasNext()) + { + results.add(iterator.next()); + } + + if (identifiers.size() > 1) + { + // We may need to filter out some of the records. When there are duplicated + // codes among different spaces, projects or experiments the list methods + // may return too many results. Therefore we have to verify the results really + // match the identifiers list. Because it is a very rare case we + // prefer to do it this way rather than make the query more complicated and + // slower. It may only happen when there is more than one identifier + // specified though. + + identifiers.filter(results); + } + + return createExperiments(results); + + } else + { + return Collections.emptyList(); + } + } + + private List<Experiment> createExperiments(List<ExperimentRecord> records) + { + List<Experiment> result = new ArrayList<Experiment>(records.size()); + for (ExperimentRecord record : records) + { + result.add(createExperiment(record)); + } + return result; + } + + private Experiment createExperiment(ExperimentRecord record) + { + ExperimentIdentifier experimentIdentifier = + new ExperimentIdentifier(createDatabaseInstanceIdentifier(record) + .getDatabaseInstanceCode(), record.s_code, record.pr_code, record.e_code); + + Experiment experiment = new Experiment(); + experiment.setFetchOptions(new ExperimentFetchOptions()); + experiment.setId(record.e_id); + experiment.setModificationDate(record.e_modification_timestamp); + experiment.setCode(record.e_code); + experiment.setPermId(record.e_perm_id); + experiment.setPermlink(PermlinkUtilities.createPermlinkURL(baseIndexURL, + EntityKind.EXPERIMENT, record.e_perm_id)); + experiment.setExperimentType(createExperimentType(record)); + experiment.setIdentifier(experimentIdentifier.toString()); + experiment.setProject(createProject(record)); + experiment.setRegistrator(createPerson(record)); + experiment.setRegistrationDate(record.e_registration_timestamp); + experiment.setModificationDate(record.e_modification_timestamp); + return experiment; + } + + private ExperimentType createExperimentType(ExperimentRecord record) + { + ExperimentType experimentType = new ExperimentType(); + experimentType.setCode(record.et_code); + experimentType.setDescription(record.et_description); + experimentType.setDatabaseInstance(createDatabaseInstance(record)); + return experimentType; + } + + private DatabaseInstanceIdentifier createDatabaseInstanceIdentifier(ExperimentRecord record) + { + return new DatabaseInstanceIdentifier(record.d_is_original_source, record.d_code); + } + + private DatabaseInstance createDatabaseInstance(ExperimentRecord record) + { + DatabaseInstance instance = new DatabaseInstance(); + instance.setId(record.d_id); + instance.setCode(record.d_code); + instance.setUuid(record.d_uuid); + instance.setHomeDatabase(record.d_is_original_source); + instance.setIdentifier(createDatabaseInstanceIdentifier(record).toString()); + return instance; + } + + private Space createSpace(ExperimentRecord record) + { + SpaceIdentifier spaceIdentifier = + new SpaceIdentifier(createDatabaseInstanceIdentifier(record) + .getDatabaseInstanceCode(), record.s_code); + + Space space = new Space(); + space.setId(record.s_id); + space.setCode(record.s_code); + space.setDescription(record.s_description); + space.setInstance(createDatabaseInstance(record)); + space.setRegistrationDate(record.s_registration_timestamp); + space.setIdentifier(spaceIdentifier.toString()); + return space; + } + + private Person createPerson(ExperimentRecord record) + { + Person person = new Person(); + person.setFirstName(record.pe_first_name); + person.setLastName(record.pe_last_name); + person.setEmail(record.pe_email); + person.setUserId(record.pe_user_id); + person.setDatabaseInstance(createDatabaseInstance(record)); + person.setRegistrationDate(record.pe_registration_timestamp); + return person; + } + + private Project createProject(ExperimentRecord record) + { + ProjectIdentifier projectIdentifier = + new ProjectIdentifier(createDatabaseInstanceIdentifier(record) + .getDatabaseInstanceCode(), record.s_code, record.pr_code); + + Project project = new Project(); + project.setId(record.pr_id); + project.setModificationDate(record.pr_modification_timestamp); + project.setRegistrationDate(record.pr_registration_timestamp); + project.setCode(record.pr_code); + project.setDescription(record.pr_description); + project.setSpace(createSpace(record)); + project.setRegistrationDate(record.pr_registration_timestamp); + project.setIdentifier(projectIdentifier.toString()); + return project; + } + + private class ProjectIdentifiers + { + private Set<ProjectIdentifier> identifiersSet; + + private Set<String> databaseInstanceCodes; + + private Set<String> spaceCodes; + + private Set<String> projectCodes; + + public ProjectIdentifiers(List<? extends ProjectIdentifier> identifiers) + { + identifiersSet = new HashSet<ProjectIdentifier>(identifiers.size()); + databaseInstanceCodes = new HashSet<String>(identifiers.size()); + spaceCodes = new HashSet<String>(identifiers.size()); + projectCodes = new HashSet<String>(identifiers.size()); + + for (ProjectIdentifier identifier : identifiers) + { + if (StringUtils.isBlank(identifier.getDatabaseInstanceCode())) + { + identifier.setDatabaseInstanceCode(daoFactory.getHomeDatabaseInstance() + .getCode()); + } + identifiersSet.add(identifier); + databaseInstanceCodes.add(identifier.getDatabaseInstanceCode()); + spaceCodes.add(identifier.getSpaceCode()); + projectCodes.add(identifier.getProjectCode()); + } + } + + public String[] getDatabaseInstanceCodes() + { + return databaseInstanceCodes.toArray(new String[databaseInstanceCodes.size()]); + } + + public String[] getSpaceCodes() + { + return spaceCodes.toArray(new String[spaceCodes.size()]); + } + + public String[] getProjectCodes() + { + return projectCodes.toArray(new String[projectCodes.size()]); + } + + public boolean contains(ProjectIdentifier identifier) + { + return identifiersSet.contains(identifier); + } + + public int size() + { + return identifiersSet.size(); + } + + public void filter(List<ExperimentRecord> records) + { + Iterator<ExperimentRecord> iterator = records.iterator(); + while (iterator.hasNext()) + { + ExperimentRecord record = iterator.next(); + ProjectIdentifier identifier = + new ProjectIdentifier(record.d_code, record.s_code, record.pr_code); + if (!contains(identifier)) + { + iterator.remove(); + } + } + } + } + + private class ExperimentIdentifiers extends ProjectIdentifiers + { + private Set<String> experimentCodes; + + public ExperimentIdentifiers(List<ExperimentIdentifier> identifiers) + { + super(identifiers); + + experimentCodes = new HashSet<String>(identifiers.size()); + + for (ExperimentIdentifier identifier : identifiers) + { + experimentCodes.add(identifier.getExperimentCode()); + } + } + + public String[] getExperimentCodes() + { + return experimentCodes.toArray(new String[experimentCodes.size()]); + } + + @Override + public void filter(List<ExperimentRecord> records) + { + Iterator<ExperimentRecord> iterator = records.iterator(); + while (iterator.hasNext()) + { + ExperimentRecord record = iterator.next(); + ExperimentIdentifier identifier = + new ExperimentIdentifier(record.d_code, record.s_code, record.pr_code, + record.e_code); + if (!contains(identifier)) + { + iterator.remove(); + } + } + } + + } + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/experimentlister/ExperimentRecord.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/experimentlister/ExperimentRecord.java new file mode 100644 index 0000000000000000000000000000000000000000..223481068fd5151db1a6b7f7912e41a9a1f6f22f --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/experimentlister/ExperimentRecord.java @@ -0,0 +1,83 @@ +/* + * Copyright 2012 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.experimentlister; + +import java.util.Date; + +/** + * @author pkupczyk + */ +public class ExperimentRecord +{ + + public Long e_id; + + public String e_perm_id; + + public String e_code; + + public Date e_registration_timestamp; + + public Date e_modification_timestamp; + + public Long et_id; + + public String et_code; + + public String et_description; + + public Long d_id; + + public String d_code; + + public Boolean d_is_original_source; + + public Date d_registration_timestamp; + + public String d_uuid; + + public Long s_id; + + public String s_code; + + public String s_description; + + public Date s_registration_timestamp; + + public Long pr_id; + + public String pr_code; + + public Date pr_registration_timestamp; + + public String pr_description; + + public Date pr_modification_timestamp; + + public Long pe_id; + + public String pe_first_name; + + public String pe_last_name; + + public String pe_user_id; + + public String pe_email; + + public Date pe_registration_timestamp; + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/experimentlister/IExperimentLister.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/experimentlister/IExperimentLister.java new file mode 100644 index 0000000000000000000000000000000000000000..9a1fb3cc4f70b1f642254297be0797918e5e07bd --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/experimentlister/IExperimentLister.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012 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.experimentlister; + +import java.util.List; + +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment; +import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentFetchOptions; +import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier; +import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier; + +/** + * @author pkupczyk + */ +public interface IExperimentLister +{ + + public List<Experiment> listExperiments(List<ExperimentIdentifier> experimentIdentifiers, + ExperimentFetchOptions experimentFetchOptions); + + public List<Experiment> listExperimentsForProjects(List<ProjectIdentifier> projectIdentifiers, + ExperimentFetchOptions experimentFetchOptions); + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/experimentlister/IExperimentListingQuery.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/experimentlister/IExperimentListingQuery.java new file mode 100644 index 0000000000000000000000000000000000000000..4c390a1cb54abb5ade64f1a4512ef93ea28eddba --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/experimentlister/IExperimentListingQuery.java @@ -0,0 +1,55 @@ +/* + * Copyright 2012 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.experimentlister; + +import net.lemnik.eodsql.BaseQuery; +import net.lemnik.eodsql.DataIterator; +import net.lemnik.eodsql.Select; + +import ch.systemsx.cisd.openbis.generic.server.dataaccess.db.StringArrayMapper; + +/** + * @author pkupczyk + */ +public interface IExperimentListingQuery extends BaseQuery +{ + + public static final String LIST_EXPERIMENTS = + " SELECT e.id as e_id, e.perm_id as e_perm_id, e.code as e_code, e.registration_timestamp as e_registration_timestamp, e.modification_timestamp as e_modification_timestamp," + + " et.id as et_id, et.code as et_code, et.description as et_description," + + " d.id as d_id, d.code as d_code, d.is_original_source as d_is_original_source, d.registration_timestamp as d_registration_timestamp, d.uuid as d_uuid," + + " s.id as s_id, s.code as s_code, s.description as s_description, s.registration_timestamp as s_registration_timestamp," + + " pr.id as pr_id, pr.code as pr_code, pr.registration_timestamp as pr_registration_timestamp, pr.description as pr_description, pr.modification_timestamp as pr_modification_timestamp," + + " pe.id as pe_id, pe.first_name as pe_first_name, pe.last_name as pe_last_name, pe.user_id as pe_user_id, pe.email as pe_email, pe.registration_timestamp as pe_registration_timestamp" + + " FROM experiments e, experiment_types et, database_instances d, spaces s, projects pr, persons pe WHERE" + + " e.exty_id = et.id AND e.proj_id = pr.id AND" + + " pr.space_id = s.id AND s.dbin_id = d.id AND e.pers_id_registerer = pe.id"; + + @Select(sql = LIST_EXPERIMENTS + + " AND d.code = any(?{1}) AND s.code = any(?{2}) AND pr.code = any(?{3}) AND e.code = any(?{4})", parameterBindings = + { StringArrayMapper.class, StringArrayMapper.class, StringArrayMapper.class, + StringArrayMapper.class }) + public DataIterator<ExperimentRecord> listExperiments(String[] databaseInstanceCodes, + String[] spaceCodes, String[] projectCodes, String[] experimentCodes); + + @Select(sql = LIST_EXPERIMENTS + + " AND d.code = any(?{1}) AND s.code = any(?{2}) AND pr.code = any(?{3})", parameterBindings = + { StringArrayMapper.class, StringArrayMapper.class, StringArrayMapper.class }) + public DataIterator<ExperimentRecord> listExperimentsForProjects( + String[] databaseInstanceCodes, String[] spaceCodes, String[] projectCodes); + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/SpaceDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/SpaceDAO.java index 7b6687ad3f7e6f8cf7818267a8573a38101f96fb..7a785a98d1f180498b67b887f5872e700d004de7 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/SpaceDAO.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/SpaceDAO.java @@ -19,6 +19,7 @@ package ch.systemsx.cisd.openbis.generic.server.dataaccess.db; import java.util.List; import org.apache.log4j.Logger; +import org.hibernate.FetchMode; import org.hibernate.SessionFactory; import org.hibernate.criterion.DetachedCriteria; import org.hibernate.criterion.Restrictions; @@ -46,8 +47,8 @@ final class SpaceDAO extends AbstractGenericEntityDAO<SpacePE> implements ISpace * This logger does not output any SQL statement. If you want to do so, you had better set an * appropriate debugging level for class {@link JdbcAccessor}. </p> */ - private static final Logger operationLog = - LogFactory.getLogger(LogCategory.OPERATION, SpaceDAO.class); + private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, + SpaceDAO.class); SpaceDAO(final SessionFactory sessionFactory, final DatabaseInstancePE databaseInstance) { @@ -80,7 +81,9 @@ final class SpaceDAO extends AbstractGenericEntityDAO<SpacePE> implements ISpace public final List<SpacePE> listSpaces() throws DataAccessException { - final List<SpacePE> list = cast(getHibernateTemplate().loadAll(getEntityClass())); + final DetachedCriteria criteria = DetachedCriteria.forClass(getEntityClass()); + criteria.setFetchMode("registrator", FetchMode.JOIN); + final List<SpacePE> list = cast(getHibernateTemplate().findByCriteria(criteria)); if (operationLog.isDebugEnabled()) { operationLog.debug(String.format("%s(): %d space(s) have been found.", MethodUtils @@ -95,6 +98,7 @@ final class SpaceDAO extends AbstractGenericEntityDAO<SpacePE> implements ISpace assert databaseInstance != null : "Unspecified database instance."; final DetachedCriteria criteria = DetachedCriteria.forClass(getEntityClass()); + criteria.setFetchMode("registrator", FetchMode.JOIN); criteria.add(Restrictions.eq("databaseInstance", databaseInstance)); final List<SpacePE> list = cast(getHibernateTemplate().findByCriteria(criteria)); if (operationLog.isDebugEnabled()) diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/AbstractServerLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/AbstractServerLogger.java index 98c6faf67f6beeab4e54b1ad0fd1e4bac8cf3d56..4a12bed3e0aef4fd87b8aa4292622a4941e07239 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/AbstractServerLogger.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/AbstractServerLogger.java @@ -275,6 +275,12 @@ public abstract class AbstractServerLogger implements IServer logAccess(sessionToken, "set_base_url", "BASE_URL(%s)", baseURL); } + public String getBaseIndexURL(String sessionToken) + { + logAccess(sessionToken, "get_base_url", ""); + return null; + } + public void setSessionUser(String sessionToken, String userID) { logMessage(authLog, Level.INFO, sessionToken, "set_session_user", "USER(%s)", new Object[] 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 90260a91c69e045158e639e9fe0e3fb8bd5b1823..0d0aa88743064fd3e281587508a76693e314ed6e 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 @@ -78,6 +78,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetShareId; import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetUpdatesDTO; import ch.systemsx.cisd.openbis.generic.shared.dto.DataStoreServerInfo; import ch.systemsx.cisd.openbis.generic.shared.dto.EntityCollectionForCreationOrUpdate; +import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentFetchOptions; import ch.systemsx.cisd.openbis.generic.shared.dto.ListSamplesByPropertyCriteria; import ch.systemsx.cisd.openbis.generic.shared.dto.NewExternalData; import ch.systemsx.cisd.openbis.generic.shared.dto.NewProperty; @@ -474,6 +475,28 @@ public interface IETLLIMSService extends IServer, ISessionProvider @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class) ProjectIdentifier projectIdentifier); + /** + * List experiments for a given list of experiment identifiers. + */ + @Transactional(readOnly = true) + @RolesAllowed( + { RoleWithHierarchy.SPACE_OBSERVER, RoleWithHierarchy.SPACE_ETL_SERVER }) + public List<Experiment> listExperiments(String sessionToken, + @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class) + List<ExperimentIdentifier> experimentIdentifiers, + ExperimentFetchOptions experimentFetchOptions); + + /** + * List experiments for a given list of project identifiers. + */ + @Transactional(readOnly = true) + @RolesAllowed( + { RoleWithHierarchy.SPACE_OBSERVER, RoleWithHierarchy.SPACE_ETL_SERVER }) + public List<Experiment> listExperimentsForProjects(String sessionToken, + @AuthorizationGuard(guardClass = SpaceIdentifierPredicate.class) + List<ProjectIdentifier> projectIdentifiers, + ExperimentFetchOptions experimentFetchOptions); + /** * List all projects that the user can see. */ diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IServer.java index 14c1719624eb27e13d713c8878f2c87d51f1a003..fb5b129fd61bc1f76c78410262de9c6288d590bd 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IServer.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IServer.java @@ -62,7 +62,7 @@ public interface IServer extends ISessionProvider */ @Transactional public SessionContextDTO tryToAuthenticate(final String user, final String password); - + @Transactional public SessionContextDTO tryToAuthenticateAnonymously(); @@ -76,11 +76,15 @@ public interface IServer extends ISessionProvider @Transactional public void setBaseIndexURL(String sessionToken, String baseIndexURL); + @Transactional + public String getBaseIndexURL(String sessionToken); + @Transactional public DisplaySettings getDefaultDisplaySettings(String sessionToken); @Transactional - public void saveDisplaySettings(String sessionToken, DisplaySettings displaySettings, int maxEntityVisits); + public void saveDisplaySettings(String sessionToken, DisplaySettings displaySettings, + int maxEntityVisits); /** * Lists grid custom columns for a given grid id. diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Experiment.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Experiment.java index 48eda19dfaa03e0a4d0ba8fd713c184ed697b55b..9cad5cad46933abcab143cc3478dcf6ef3898ea0 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Experiment.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Experiment.java @@ -24,6 +24,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolderWit import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityWithDeletionInformation; import ch.systemsx.cisd.openbis.generic.shared.basic.IIdAndCodeHolder; import ch.systemsx.cisd.openbis.generic.shared.basic.IPermIdHolder; +import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentFetchOptions; /** * The <i>GWT</i> equivalent to ExperimentPE. @@ -56,6 +57,8 @@ public class Experiment extends CodeWithRegistration<Experiment> implements private String permlink; + private ExperimentFetchOptions fetchOptions; + public String getPermlink() { return permlink; @@ -126,6 +129,16 @@ public class Experiment extends CodeWithRegistration<Experiment> implements this.attachments = attachments; } + public ExperimentFetchOptions getFetchOptions() + { + return fetchOptions; + } + + public void setFetchOptions(ExperimentFetchOptions fetchOptions) + { + this.fetchOptions = fetchOptions; + } + // // IIdentifierHolder // diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentFetchOption.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentFetchOption.java new file mode 100644 index 0000000000000000000000000000000000000000..5d530699cae0c3352801b26d6974de97f6baf032 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentFetchOption.java @@ -0,0 +1,27 @@ +/* + * Copyright 2012 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.openbis.generic.shared.dto; + +/** + * @author pkupczyk + */ +public enum ExperimentFetchOption +{ + + BASIC, PROPERTIES, PROPERTIES_OF_PROPERTIES, SCRIPTS; + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentFetchOptions.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentFetchOptions.java new file mode 100644 index 0000000000000000000000000000000000000000..e21ef67fffdb1c7466df56440054c75e16b05fd3 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentFetchOptions.java @@ -0,0 +1,100 @@ +/* + * Copyright 2012 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.openbis.generic.shared.dto; + +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; + +/** + * @author pkupczyk + */ +public class ExperimentFetchOptions implements Serializable +{ + + private static final long serialVersionUID = 1L; + + private Set<ExperimentFetchOption> options = new HashSet<ExperimentFetchOption>(); + + public ExperimentFetchOptions(ExperimentFetchOption... options) + { + // add BASIC option by default + addOption(ExperimentFetchOption.BASIC); + + if (options != null) + { + for (ExperimentFetchOption option : options) + { + addOption(option); + } + } + } + + public void addOption(ExperimentFetchOption option) + { + if (option == null) + { + throw new IllegalArgumentException("Option cannot be null"); + } + options.add(option); + } + + public boolean containsOption(ExperimentFetchOption option) + { + return options.contains(option); + } + + public boolean containsOnlyOption(ExperimentFetchOption option) + { + return containsOption(option) && options.size() == 1; + } + + @Override + public String toString() + { + return options.toString(); + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((options == null) ? 0 : options.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ExperimentFetchOptions other = (ExperimentFetchOptions) obj; + if (options == null) + { + if (other.options != null) + return false; + } else if (!options.equals(other.options)) + return false; + return true; + } + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentPE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentPE.java index d515a650bbbaf5aee24fc548ac4e8917cd8392f0..ddb10120db864cafaf3fdb3da88788d9bb208db7 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentPE.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentPE.java @@ -215,7 +215,7 @@ public class ExperimentPE extends AttachmentHolderPE implements project.addExperiment(this); } - @ManyToOne(fetch = FetchType.EAGER) + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = ColumnNames.STUDY_OBJECT_COLUMN, updatable = false) public MaterialPE getStudyObject() { diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/identifier/DatabaseInstanceIdentifier.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/identifier/DatabaseInstanceIdentifier.java index 03702372acc84af3c2b005c0e8e5f2b101bcd457..ff16b0d7eed1d421111c6c4d02edd9b3c036cc52 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/identifier/DatabaseInstanceIdentifier.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/identifier/DatabaseInstanceIdentifier.java @@ -58,6 +58,17 @@ public class DatabaseInstanceIdentifier implements Serializable this.databaseInstanceCode = databaseInstanceCode; } + public DatabaseInstanceIdentifier(boolean isOriginalSource, String databaseInstanceCode) + { + if (isOriginalSource) + { + this.databaseInstanceCode = HOME; + } else + { + this.databaseInstanceCode = databaseInstanceCode; + } + } + /** * Usually you should not access database instance code directly. Look for appropriate helpers. * diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceDatabaseTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceDatabaseTest.java new file mode 100644 index 0000000000000000000000000000000000000000..dc66a400a8bd7a8590e22e5404c867683bc579d2 --- /dev/null +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceDatabaseTest.java @@ -0,0 +1,119 @@ +/* + * Copyright 2012 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 static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertTrue; + +import java.sql.SQLException; +import java.util.Collections; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import ch.systemsx.cisd.openbis.generic.server.dataaccess.db.AbstractDAOTest; +import ch.systemsx.cisd.openbis.generic.shared.IETLLIMSService; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment; +import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentFetchOption; +import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentFetchOptions; +import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier; +import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier; + +/** + * @author pkupczyk + */ +@Test(groups = + { "db", "dataset" }) +public class ETLServiceDatabaseTest extends AbstractDAOTest +{ + @Autowired + private IETLLIMSService service; + + private String sessionToken; + + @BeforeClass(alwaysRun = true) + public void init() throws SQLException + { + sessionToken = service.tryToAuthenticate("test", "password").getSessionToken(); + } + + @Test + public void testListExperimentsWithBasicFetchOptions() + { + List<ExperimentIdentifier> identifiers = + Collections.singletonList(new ExperimentIdentifier("CISD", "CISD", "NEMO", "EXP1")); + + List<Experiment> result = + service.listExperiments(sessionToken, identifiers, new ExperimentFetchOptions()); + + assertEquals(1, result.size()); + assertTrue(result.get(0).getFetchOptions().containsOnlyOption(ExperimentFetchOption.BASIC)); + } + + @Test + public void testListExperimentsWithAllFetchOptions() + { + List<ExperimentIdentifier> identifiers = + Collections.singletonList(new ExperimentIdentifier("CISD", "CISD", "NEMO", "EXP1")); + + List<Experiment> result = + service.listExperiments(sessionToken, identifiers, new ExperimentFetchOptions( + ExperimentFetchOption.values())); + + assertEquals(1, result.size()); + + for (ExperimentFetchOption option : ExperimentFetchOption.values()) + { + assertTrue(result.get(0).getFetchOptions().containsOption(option)); + } + } + + @Test + public void testListExperimentsForProjectsWithBasicFetchOptions() + { + List<ProjectIdentifier> identifiers = + Collections.singletonList(new ProjectIdentifier("CISD", "CISD", "NOE")); + + List<Experiment> result = + service.listExperimentsForProjects(sessionToken, identifiers, + new ExperimentFetchOptions()); + + assertEquals(1, result.size()); + assertTrue(result.get(0).getFetchOptions().containsOnlyOption(ExperimentFetchOption.BASIC)); + } + + @Test + public void testListExperimentsForProjectsWithAllFetchOptions() + { + List<ProjectIdentifier> identifiers = + Collections.singletonList(new ProjectIdentifier("CISD", "CISD", "NOE")); + + List<Experiment> result = + service.listExperimentsForProjects(sessionToken, identifiers, + new ExperimentFetchOptions(ExperimentFetchOption.values())); + + assertEquals(1, result.size()); + + for (ExperimentFetchOption option : ExperimentFetchOption.values()) + { + assertTrue(result.get(0).getFetchOptions().containsOption(option)); + } + } + +} diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/experimentlister/ExperimentListerTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/experimentlister/ExperimentListerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..fcab8ea185404ce8e4276dd086ebd28d5ab41592 --- /dev/null +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/experimentlister/ExperimentListerTest.java @@ -0,0 +1,271 @@ +/* + * Copyright 2009 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.openbis.generic.server.business.bo.experimentlister; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertTrue; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.apache.commons.collections.map.HashedMap; +import org.springframework.beans.factory.annotation.Autowired; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import ch.systemsx.cisd.openbis.generic.server.business.bo.common.EntityListingTestUtils; +import ch.systemsx.cisd.openbis.generic.server.dataaccess.db.AbstractDAOTest; +import ch.systemsx.cisd.openbis.generic.shared.IETLLIMSService; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseInstance; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentType; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space; +import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentFetchOption; +import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentFetchOptions; +import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier; +import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier; + +/** + * Test cases for {@link IExperimentListingQuery}. + * + * @author Piotr Kupczyk + */ +@Test(groups = + { "db", "dataset" }) +public class ExperimentListerTest extends AbstractDAOTest +{ + + @Autowired + private IETLLIMSService service; + + private IExperimentLister lister; + + private String sessionToken; + + @BeforeClass(alwaysRun = true) + public void init() throws SQLException + { + sessionToken = service.tryToAuthenticate("test", "password").getSessionToken(); + lister = + new ExperimentLister(daoFactory, EntityListingTestUtils.createQuery(daoFactory, + IExperimentListingQuery.class), service.getBaseIndexURL(sessionToken)); + } + + @Test + public void testListExperimentsForEmptyExperimentIdentifiersListShouldReturnEmptyList() + { + List<Experiment> result = + lister.listExperiments(new ArrayList<ExperimentIdentifier>(), + new ExperimentFetchOptions()); + + assertEqualToExperimentsWithIdentifiers(new ArrayList<ExperimentIdentifier>(), result); + } + + @Test + public void testListExperimentsForExistingExperimentIdentifierShouldReturnExperiment() + { + List<ExperimentIdentifier> identifiers = + Collections.singletonList(new ExperimentIdentifier("CISD", "CISD", "NEMO", "EXP1")); + + List<Experiment> result = lister.listExperiments(identifiers, new ExperimentFetchOptions()); + + assertEqualToExperimentsWithIdentifiers(identifiers, result); + } + + @Test + public void testListExperimentsForExistingExperimentIdentifiersShouldReturnExperiments() + { + List<ExperimentIdentifier> identifiers = new ArrayList<ExperimentIdentifier>(); + identifiers.add(new ExperimentIdentifier("CISD", "CISD", "NEMO", "EXP-TEST-1")); + identifiers.add(new ExperimentIdentifier("CISD", "CISD", "NOE", "EXP-TEST-2")); + + List<Experiment> result = lister.listExperiments(identifiers, new ExperimentFetchOptions()); + + assertEqualToExperimentsWithIdentifiers(identifiers, result); + } + + @Test + public void testListExperimentsForExistingAndNotExistingExperimentIdentifiersShouldReturnExistingExperiments() + { + List<ExperimentIdentifier> identifiers = new ArrayList<ExperimentIdentifier>(); + identifiers.add(new ExperimentIdentifier("CISD", "CISD", "NEMO", "EXP-TEST-1")); + identifiers.add(new ExperimentIdentifier("CISD", "CISD", "NOE", "EXP-TEST-10")); + + List<Experiment> result = lister.listExperiments(identifiers, new ExperimentFetchOptions()); + + identifiers.remove(1); + assertEqualToExperimentsWithIdentifiers(identifiers, result); + } + + @Test + public void testListExperimentsForProjectsForEmptyProjectIdentifiersListShouldReturnEmptyList() + { + List<Experiment> result = + lister.listExperimentsForProjects(new ArrayList<ProjectIdentifier>(), + new ExperimentFetchOptions()); + + assertEqualToExperimentsWithIdentifiers(new ArrayList<ExperimentIdentifier>(), result); + } + + @Test + public void testListExperimentsForProjectsForExistingProjectShouldReturnProjectExperiments() + { + List<ProjectIdentifier> projectIdentifiers = + Collections.singletonList(new ProjectIdentifier("CISD", "CISD", "NEMO")); + + List<ExperimentIdentifier> experimentIdentifiers = new ArrayList<ExperimentIdentifier>(); + experimentIdentifiers.add(new ExperimentIdentifier("CISD", "CISD", "NEMO", "EXP1")); + experimentIdentifiers.add(new ExperimentIdentifier("CISD", "CISD", "NEMO", "EXP10")); + experimentIdentifiers.add(new ExperimentIdentifier("CISD", "CISD", "NEMO", "EXP11")); + experimentIdentifiers.add(new ExperimentIdentifier("CISD", "CISD", "NEMO", "EXP-TEST-1")); + experimentIdentifiers.add(new ExperimentIdentifier("CISD", "CISD", "NEMO", "EXP-TEST-2")); + + List<Experiment> result = + lister.listExperimentsForProjects(projectIdentifiers, new ExperimentFetchOptions()); + + assertEqualToExperimentsWithIdentifiers(experimentIdentifiers, result); + } + + @Test + public void testListExperimentsForProjectsForExistingProjectsShouldReturnProjectsExperiments() + { + List<ProjectIdentifier> projectIdentifiers = new ArrayList<ProjectIdentifier>(); + projectIdentifiers.add(new ProjectIdentifier("CISD", "CISD", "NEMO")); + projectIdentifiers.add(new ProjectIdentifier("CISD", "CISD", "NOE")); + + List<ExperimentIdentifier> experimentIdentifiers = new ArrayList<ExperimentIdentifier>(); + experimentIdentifiers.add(new ExperimentIdentifier("CISD", "CISD", "NEMO", "EXP1")); + experimentIdentifiers.add(new ExperimentIdentifier("CISD", "CISD", "NEMO", "EXP10")); + experimentIdentifiers.add(new ExperimentIdentifier("CISD", "CISD", "NEMO", "EXP11")); + experimentIdentifiers.add(new ExperimentIdentifier("CISD", "CISD", "NEMO", "EXP-TEST-1")); + experimentIdentifiers.add(new ExperimentIdentifier("CISD", "CISD", "NEMO", "EXP-TEST-2")); + experimentIdentifiers.add(new ExperimentIdentifier("CISD", "CISD", "NOE", "EXP-TEST-2")); + + List<Experiment> result = + lister.listExperimentsForProjects(projectIdentifiers, new ExperimentFetchOptions()); + + assertEqualToExperimentsWithIdentifiers(experimentIdentifiers, result); + } + + @Test + public void testListExperimentsForProjectsForExistingAndNotExistingProjectIdentifiersShouldReturnExistingProjectsExperiments() + { + List<ProjectIdentifier> projectIdentifiers = new ArrayList<ProjectIdentifier>(); + projectIdentifiers.add(new ProjectIdentifier("CISD", "CISD", "NOE")); + projectIdentifiers.add(new ProjectIdentifier("CISD", "CISD", "UNKNOWN-PROJECT")); + + List<ExperimentIdentifier> experimentIdentifiers = + Collections.singletonList(new ExperimentIdentifier("CISD", "CISD", "NOE", + "EXP-TEST-2")); + + List<Experiment> result = + lister.listExperimentsForProjects(projectIdentifiers, new ExperimentFetchOptions()); + + assertEqualToExperimentsWithIdentifiers(experimentIdentifiers, result); + } + + private void assertEqualToExperimentsWithIdentifiers( + List<ExperimentIdentifier> expectedExperimentsIdentifiers, + List<Experiment> actualExperiments) + { + assertEquals(expectedExperimentsIdentifiers.size(), actualExperiments.size()); + + Map<Long, Experiment> expectedExperimentsMap = new HashedMap<Long, Experiment>(); + for (ExperimentIdentifier expectedExperimentIdentifier : expectedExperimentsIdentifiers) + { + Experiment expectedExperiment = + service.tryToGetExperiment(sessionToken, expectedExperimentIdentifier); + expectedExperimentsMap.put(expectedExperiment.getId(), expectedExperiment); + } + + for (Experiment actualExperiment : actualExperiments) + { + Experiment expectedExperiment = expectedExperimentsMap.get(actualExperiment.getId()); + assertNotNull(expectedExperiment); + assertEqualsToExperiment(expectedExperiment, actualExperiment); + } + + } + + private void assertEqualsToExperiment(Experiment expected, Experiment actual) + { + assertEquals(expected.getId(), actual.getId()); + assertEquals(expected.getIdentifier(), actual.getIdentifier()); + assertEquals(expected.getCode(), actual.getCode()); + assertEquals(expected.getPermId(), actual.getPermId()); + assertEquals(expected.getPermlink(), actual.getPermlink()); + assertEquals(expected.getRegistrationDate(), actual.getRegistrationDate()); + assertEquals(expected.getModificationDate(), actual.getModificationDate()); + assertEqualsToExperimentType(expected.getExperimentType(), actual.getExperimentType()); + assertEqualsToProject(expected.getProject(), actual.getProject()); + assertEqualsToPerson(expected.getRegistrator(), actual.getRegistrator()); + assertTrue(actual.getFetchOptions().containsOnlyOption(ExperimentFetchOption.BASIC)); + } + + private void assertEqualsToExperimentType(ExperimentType expected, ExperimentType actual) + { + assertEquals(expected.getCode(), actual.getCode()); + assertEquals(expected.getDescription(), actual.getDescription()); + assertEqualsToDatabaseInstance(expected.getDatabaseInstance(), actual.getDatabaseInstance()); + } + + private void assertEqualsToProject(Project expected, Project actual) + { + assertEquals(expected.getId(), actual.getId()); + assertEquals(expected.getIdentifier(), actual.getIdentifier()); + assertEquals(expected.getCode(), actual.getCode()); + assertEquals(expected.getDescription(), actual.getDescription()); + assertEquals(expected.getModificationDate(), actual.getModificationDate()); + assertEquals(expected.getRegistrationDate(), actual.getRegistrationDate()); + assertEqualsToSpace(expected.getSpace(), actual.getSpace()); + } + + private void assertEqualsToPerson(Person expected, Person actual) + { + assertEquals(expected.getEmail(), actual.getEmail()); + assertEquals(expected.getFirstName(), actual.getFirstName()); + assertEquals(expected.getLastName(), actual.getLastName()); + assertEquals(expected.getRegistrationDate(), actual.getRegistrationDate()); + assertEquals(expected.getUserId(), actual.getUserId()); + assertEqualsToDatabaseInstance(expected.getDatabaseInstance(), actual.getDatabaseInstance()); + } + + private void assertEqualsToSpace(Space expected, Space actual) + { + assertEquals(expected.getId(), actual.getId()); + assertEquals(expected.getIdentifier(), actual.getIdentifier()); + assertEquals(expected.getCode(), actual.getCode()); + assertEquals(expected.getDescription(), actual.getDescription()); + assertEquals(expected.getRegistrationDate(), actual.getRegistrationDate()); + assertEqualsToDatabaseInstance(expected.getInstance(), actual.getInstance()); + } + + private void assertEqualsToDatabaseInstance(DatabaseInstance expected, DatabaseInstance actual) + { + assertEquals(expected.getId(), actual.getId()); + assertEquals(expected.getIdentifier(), actual.getIdentifier()); + assertEquals(expected.getCode(), actual.getCode()); + assertEquals(expected.getUuid(), actual.getUuid()); + } + +} \ No newline at end of file