diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/sample/FullSampleIdentifier.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/sample/FullSampleIdentifier.java index ba2b50955a1a53da8680a26022788e6c7aed18d9..441695289f1781ab2fd53d7c048cf9f5463450a9 100644 --- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/sample/FullSampleIdentifier.java +++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/sample/FullSampleIdentifier.java @@ -16,6 +16,10 @@ package ch.ethz.sis.openbis.generic.server.api.v3.executor.sample; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + import org.apache.commons.lang.StringUtils; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.sample.SampleIdentifier; @@ -26,7 +30,7 @@ import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.sample.SampleIdentifier; * * @author Franz-Josef Elmer */ -class FullSampleIdentifier +public class FullSampleIdentifier { private static final String CODE_CHAR_PATTERN = "a-zA-Z0-9_\\-\\."; private static final String CODE_CHARS = "[" + CODE_CHAR_PATTERN + "]+"; @@ -35,7 +39,7 @@ class FullSampleIdentifier private SampleIdentifierParts sampleIdentifierParts; private String sampleCode; - FullSampleIdentifier(String sampleIdentifier) + public FullSampleIdentifier(String sampleIdentifier, String homeSpaceCodeOrNull) { String[] parts = extractParts(sampleIdentifier); String spaceCode = null; @@ -56,35 +60,58 @@ class FullSampleIdentifier projectCode = parts[2]; code = parts[3]; } + if (spaceCode != null && spaceCode.isEmpty() && homeSpaceCodeOrNull != null) + { + spaceCode = homeSpaceCodeOrNull; + } - String[] splittedCode = splitCode(code, sampleIdentifier); - if (splittedCode.length == 2) + List<String> splittedCode = splitCode(code, sampleIdentifier); + if (splittedCode.size() == 2) { - containerCode = splittedCode[0]; - plainSampleCode = splittedCode[1]; + containerCode = splittedCode.get(0); + plainSampleCode = splittedCode.get(1); } else { - plainSampleCode = splittedCode[0]; + plainSampleCode = splittedCode.get(0); } //Code format validation - verifyCodePattern(spaceCode); - verifyCodePattern(projectCode); - verifyCodePattern(containerCode); - verifyCodePattern(plainSampleCode); + verifyCodePattern(spaceCode, "Space code"); + verifyCodePattern(projectCode, "Project code"); + verifyCodePattern(containerCode, "Container sample code"); + verifyCodePattern(plainSampleCode, containerCode == null ? "Sample code" : "Sample subcode"); sampleCode = plainSampleCode; sampleIdentifierParts = new SampleIdentifierParts(spaceCode, projectCode, containerCode); } - private String[] splitCode(String code, String sampleIdentifier) + private List<String> splitCode(String code, String sampleIdentifier) { - String[] splittedCode = code.split(":"); - if (splittedCode.length > 2) + String delim = ":"; + StringTokenizer tokenizer = new StringTokenizer(code, delim, true); + int numberOfDelims = 0; + List<String> tokens = new ArrayList<>(); + while (tokenizer.hasMoreTokens()) + { + String token = tokenizer.nextToken(); + if (delim.equals(token)) + { + numberOfDelims++; + } else + { + tokens.add(token); + } + } + if (numberOfDelims > 1) + { + throw new IllegalArgumentException("Sample code can not contain more than one '" + delim + "': " + + sampleIdentifier); + } + if (numberOfDelims != tokens.size() - 1) { - throw new IllegalArgumentException("Sample code can not contain more than one ':': " + sampleIdentifier); + throw new IllegalArgumentException("Sample code starts or ends with '" + delim + "': " + sampleIdentifier); } - return splittedCode; + return tokens; } private String[] extractParts(String sampleIdentifier) @@ -110,19 +137,29 @@ class FullSampleIdentifier return parts; } - private void verifyCodePattern(String code) { - if(code != null && code.matches(CODE_PATTERN) == false) { - throw new IllegalArgumentException("Code field containing other characters than letters, numbers, '_', '-' and '.': " + code); + private void verifyCodePattern(String code, String partName) + { + if (code == null) + { + return; } - } - + if (code.length() == 0) + { + throw new IllegalArgumentException(partName + " can not be an empty string."); + } + if (code.matches(CODE_PATTERN) == false) + { + throw new IllegalArgumentException(partName + " containing other characters than letters, numbers, " + + "'_', '-' and '.': " + code); + } + } - SampleIdentifierParts getParts() + public SampleIdentifierParts getParts() { return sampleIdentifierParts; } - String getSampleCode() + public String getSampleCode() { return sampleCode; } diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/sample/ListSampleTechIdByIdentifier.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/sample/ListSampleTechIdByIdentifier.java index 366cf9f11f03d5bd502d6870bac01be42b0fc8ff..a1fd1e470f13179c6efa16172134c66efa9d3126 100644 --- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/sample/ListSampleTechIdByIdentifier.java +++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/sample/ListSampleTechIdByIdentifier.java @@ -27,8 +27,6 @@ import net.lemnik.eodsql.QueryTool; import ch.ethz.sis.openbis.generic.server.api.v3.executor.common.TechIdStringIdentifierRecord; import ch.ethz.sis.openbis.generic.server.api.v3.helper.common.AbstractListTechIdById; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.sample.SampleIdentifier; -import ch.systemsx.cisd.openbis.generic.shared.basic.CodeConverter; -import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFactory; /** * @@ -53,37 +51,7 @@ public class ListSampleTechIdByIdentifier extends AbstractListTechIdById<SampleI @Override protected Map<Long, SampleIdentifier> createIdsByTechIdsMap(List<SampleIdentifier> ids) { - Map<SampleIdentifierParts, Map<String, SampleIdentifier>> groupedIdentifiers = new HashMap<>(); - for (SampleIdentifier sampleIdentifier : ids) - { - ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier sampleIdentifier2 - = SampleIdentifierFactory.parse(sampleIdentifier.getIdentifier()); - String spaceCode = null; - if (sampleIdentifier2.isSpaceLevel()) - { - if (sampleIdentifier2.isInsideHomeSpace()) - { - if (homeSpaceCodeOrNull == null) - { - continue; - } - spaceCode = homeSpaceCodeOrNull; - } else - { - spaceCode = CodeConverter.tryToDatabase(sampleIdentifier2.getSpaceLevel().getSpaceCode()); - } - } - String sampleSubCode = CodeConverter.tryToDatabase(sampleIdentifier2.getSampleSubCode()); - String containerCode = CodeConverter.tryToDatabase(sampleIdentifier2.tryGetContainerCode()); - SampleIdentifierParts key = new SampleIdentifierParts(spaceCode, null, containerCode); - Map<String, SampleIdentifier> identifiersByCode = groupedIdentifiers.get(key); - if (identifiersByCode == null) - { - identifiersByCode = new HashMap<>(); - groupedIdentifiers.put(key, identifiersByCode); - } - identifiersByCode.put(sampleSubCode, sampleIdentifier); - } + Map<SampleIdentifierParts, Map<String, SampleIdentifier>> groupedIdentifiers = groupIdentifiers(ids); Map<Long, SampleIdentifier> result = new HashMap<>(); SampleQuery query = QueryTool.getManagedQuery(SampleQuery.class); @@ -100,11 +68,32 @@ public class ListSampleTechIdByIdentifier extends AbstractListTechIdById<SampleI } return result; } - + + private Map<SampleIdentifierParts, Map<String, SampleIdentifier>> groupIdentifiers(List<SampleIdentifier> ids) + { + Map<SampleIdentifierParts, Map<String, SampleIdentifier>> groupedIdentifiers = new HashMap<>(); + for (SampleIdentifier sampleIdentifier : ids) + { + FullSampleIdentifier fullSampleIdentifier = new FullSampleIdentifier(sampleIdentifier.getIdentifier(), + homeSpaceCodeOrNull); + + SampleIdentifierParts key = fullSampleIdentifier.getParts(); + Map<String, SampleIdentifier> identifiersByCode = groupedIdentifiers.get(key); + if (identifiersByCode == null) + { + identifiersByCode = new HashMap<>(); + groupedIdentifiers.put(key, identifiersByCode); + } + identifiersByCode.put(fullSampleIdentifier.getSampleCode(), sampleIdentifier); + } + return groupedIdentifiers; + } + private List<TechIdStringIdentifierRecord> list(SampleQuery query, SampleIdentifierParts key, Collection<String> codes) { String[] codesArray = codes.toArray(new String[codes.size()]); String spaceCode = key.getSpaceCodeOrNull(); + String projectCode = key.getProjectCodeOrNull(); String containerCode = key.getContainerCodeOrNull(); if (spaceCode == null) { @@ -114,11 +103,19 @@ public class ListSampleTechIdByIdentifier extends AbstractListTechIdById<SampleI } return query.listSharedSampleTechIdsByContainerCodeAndCodes(containerCode, codesArray); } + if (projectCode == null) + { + if (containerCode == null) + { + return query.listSpaceSampleTechIdsByCodes(spaceCode, codesArray); + } + return query.listSpaceSampleTechIdsByContainerCodeAndCodes(spaceCode, containerCode, codesArray); + } if (containerCode == null) { - return query.listSpaceSampleTechIdsByCodes(spaceCode, codesArray); + return query.listProjectSampleTechIdsByCodes(spaceCode, projectCode, codesArray); } - return query.listSpaceSampleTechIdsByContainerCodeAndCodes(spaceCode, containerCode, codesArray); + return query.listProjectSampleTechIdsByContainerCodeAndCodes(spaceCode, projectCode, containerCode, codesArray); } } diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/sample/MapSampleByIdExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/sample/MapSampleByIdExecutor.java index 7b3cda71f60bb9007473e1f329e28b8640e08a8a..b521033dd4a5e21b82a5f9de9f6342dd8b7a4a42 100644 --- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/sample/MapSampleByIdExecutor.java +++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/sample/MapSampleByIdExecutor.java @@ -29,8 +29,8 @@ import ch.ethz.sis.openbis.generic.server.api.v3.helper.sample.ListSampleByPermI import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.sample.ISampleId; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory; import ch.systemsx.cisd.openbis.generic.server.dataaccess.ISampleDAO; -import ch.systemsx.cisd.openbis.generic.server.dataaccess.ISpaceDAO; import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE; +import ch.systemsx.cisd.openbis.generic.shared.dto.SpacePE; /** * @author pkupczyk @@ -38,22 +38,19 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE; @Component public class MapSampleByIdExecutor extends AbstractMapObjectByIdExecutor<ISampleId, SamplePE> implements IMapSampleByIdExecutor { - - private ISpaceDAO spaceDAO; - private ISampleDAO sampleDAO; @Override protected void addListers(IOperationContext context, List<IListObjectById<? extends ISampleId, SamplePE>> listers) { listers.add(new ListSampleByPermId(sampleDAO)); - listers.add(new ListSampleByIdentifier(spaceDAO, sampleDAO, context.getSession().tryGetHomeGroup())); + SpacePE space = context.getSession().tryGetHomeGroup(); + listers.add(new ListSampleByIdentifier(sampleDAO, space)); } @Autowired private void setDAOFactory(IDAOFactory daoFactory) { - spaceDAO = daoFactory.getSpaceDAO(); sampleDAO = daoFactory.getSampleDAO(); } diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/sample/SampleIdentifierParts.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/sample/SampleIdentifierParts.java index 61302519b06e6ba661900518a0ddad2ac413fd82..35e1fd85e35fccd8074c66698152f8f9bdacc5b0 100644 --- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/sample/SampleIdentifierParts.java +++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/sample/SampleIdentifierParts.java @@ -16,7 +16,7 @@ package ch.ethz.sis.openbis.generic.server.api.v3.executor.sample; -final class SampleIdentifierParts +public final class SampleIdentifierParts { private String spaceCodeOrNull; private String projectCodeOrNull; @@ -73,13 +73,6 @@ final class SampleIdentifierParts + calcHashCode(containerCodeOrNull); } - @Override - public String toString() - { - // TODO Auto-generated method stub - return super.toString(); - } - private int calcHashCode(String str) { return str == null ? 0 : str.hashCode(); diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/sample/SampleQuery.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/sample/SampleQuery.java index d1e0f3727ab7bed5904d2eda5f9ea8605fffc253..034ba69d0db097e01efd3aafd17abe0c899f2e19 100644 --- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/sample/SampleQuery.java +++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/sample/SampleQuery.java @@ -48,14 +48,29 @@ public interface SampleQuery extends ObjectQuery String[] codes); @Select(sql = "select s.id, s.code as identifier from samples s join spaces sp on s.space_id = sp.id " - + "where sp.code = ?{1} and samp_id_part_of is null and s.code = any(?{2})", parameterBindings = - { TypeMapper.class, StringArrayMapper.class }, fetchSize = FETCH_SIZE) + + "where sp.code = ?{1} and proj_id is null and samp_id_part_of is null and s.code = any(?{2})", + parameterBindings = { TypeMapper.class, StringArrayMapper.class }, fetchSize = FETCH_SIZE) public List<TechIdStringIdentifierRecord> listSpaceSampleTechIdsByCodes(String spaceCode, String[] codes); @Select(sql = "select s.id, s.code as identifier from samples s join spaces sp on s.space_id = sp.id " + "join samples cs on s.samp_id_part_of = cs.id " - + "where sp.code = ?{1} and cs.code = ?{2} and s.code = any(?{3})", parameterBindings = + + "where sp.code = ?{1} and proj_id is null and cs.code = ?{2} and s.code = any(?{3})", parameterBindings = { TypeMapper.class, TypeMapper.class, StringArrayMapper.class }, fetchSize = FETCH_SIZE) public List<TechIdStringIdentifierRecord> listSpaceSampleTechIdsByContainerCodeAndCodes(String spaceCode, String containerCode, String[] codes); + + @Select(sql = "select s.id, s.code as identifier from samples s join spaces sp on s.space_id = sp.id " + + "join projects p on s.proj_id = p.id " + + "where sp.code = ?{1} and samp_id_part_of is null and p.code = ?{2} and s.code = any(?{3})", parameterBindings = + { TypeMapper.class, TypeMapper.class, StringArrayMapper.class }, fetchSize = FETCH_SIZE) + public List<TechIdStringIdentifierRecord> listProjectSampleTechIdsByCodes(String spaceCode, + String projectCode, String[] codes); + + @Select(sql = "select s.id, s.code as identifier from samples s join spaces sp on s.space_id = sp.id " + + "join projects p on s.proj_id = p.id " + + "join samples cs on s.samp_id_part_of = cs.id " + + "where sp.code = ?{1} and p.code = ?{2} and cs.code = ?{3} and s.code = any(?{4})", parameterBindings = + { TypeMapper.class, TypeMapper.class, TypeMapper.class, StringArrayMapper.class }, fetchSize = FETCH_SIZE) + public List<TechIdStringIdentifierRecord> listProjectSampleTechIdsByContainerCodeAndCodes(String spaceCode, + String projectCode, String containerCode, String[] codes); } diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/helper/sample/ListSampleByIdentifier.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/helper/sample/ListSampleByIdentifier.java index d98f8f55342a866d73aac95c3bccb7f4f91ec262..e87fde0892b256ab083e569ccf5508372b4ad233 100644 --- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/helper/sample/ListSampleByIdentifier.java +++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/helper/sample/ListSampleByIdentifier.java @@ -16,24 +16,14 @@ package ch.ethz.sis.openbis.generic.server.api.v3.helper.sample; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; +import ch.ethz.sis.openbis.generic.server.api.v3.executor.sample.ListSampleTechIdByIdentifier; import ch.ethz.sis.openbis.generic.server.api.v3.helper.common.AbstractListObjectById; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.sample.SampleIdentifier; import ch.systemsx.cisd.openbis.generic.server.dataaccess.ISampleDAO; -import ch.systemsx.cisd.openbis.generic.server.dataaccess.ISpaceDAO; import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE; import ch.systemsx.cisd.openbis.generic.shared.dto.SpacePE; -import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFactory; -import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SpaceIdentifier; /** * @author Franz-Josef Elmer @@ -42,17 +32,15 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SpaceIdentifier; public class ListSampleByIdentifier extends AbstractListObjectById<SampleIdentifier, SamplePE> { - private ISpaceDAO spaceDAO; - private ISampleDAO sampleDAO; - private SpacePE homeSpaceOrNull; + private ListSampleTechIdByIdentifier techIdByIdentifier; - public ListSampleByIdentifier(ISpaceDAO spaceDAO, ISampleDAO sampleDAO, SpacePE homeSpaceOrNull) + public ListSampleByIdentifier(ISampleDAO sampleDAO, SpacePE homeSpaceOrNull) { - this.spaceDAO = spaceDAO; this.sampleDAO = sampleDAO; - this.homeSpaceOrNull = homeSpaceOrNull; + String homeSpaceCodeOrNull = homeSpaceOrNull == null ? null : homeSpaceOrNull.getCode(); + techIdByIdentifier = new ListSampleTechIdByIdentifier(homeSpaceCodeOrNull); } @Override @@ -64,178 +52,13 @@ public class ListSampleByIdentifier extends AbstractListObjectById<SampleIdentif @Override public SampleIdentifier createId(SamplePE sample) { - return new SampleIdentifier(sample.getIdentifier()); + return techIdByIdentifier.createId(sample.getId()); } @Override public List<SamplePE> listByIds(List<SampleIdentifier> ids) { - Map<SampleIdentifier, ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier> idMap = getIdMap(ids); - Map<String, SpacePE> spaceMap = getSpaceMap(idMap.values()); - - Map<Key, List<String>> sampleCodesBySpaceAndContainer = new HashMap<ListSampleByIdentifier.Key, List<String>>(); - - for (SampleIdentifier id : ids) - { - ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier sid = idMap.get(id); - - if (sid.isDatabaseInstanceLevel()) - { - addToMap(sampleCodesBySpaceAndContainer, null, sid); - } else if (sid.isSpaceLevel()) - { - SpaceIdentifier spaceIdentifier = sid.getSpaceLevel(); - if (sid.isInsideHomeSpace() == false) - { - String spaceCode = spaceIdentifier.getSpaceCode(); - SpacePE space = spaceMap.get(spaceCode); - if (space != null) - { - addToMap(sampleCodesBySpaceAndContainer, space, sid); - } - } else if (homeSpaceOrNull != null) - { - addToMap(sampleCodesBySpaceAndContainer, homeSpaceOrNull, sid); - } - } else - { - assert false; - } - } - List<SamplePE> result = new ArrayList<SamplePE>(); - Set<Entry<Key, List<String>>> entrySet = sampleCodesBySpaceAndContainer.entrySet(); - - for (Entry<Key, List<String>> entry : entrySet) - { - Key key = entry.getKey(); - List<String> sampleCodes = entry.getValue(); - SpacePE space = key.getSpace(); - String containerId = key.getContainerId(); - if (space == null) - { - result.addAll(sampleDAO.listByCodesAndDatabaseInstance(sampleCodes, containerId)); - } else - { - result.addAll(sampleDAO.listByCodesAndSpace(sampleCodes, containerId, space)); - } - } - return result; - } - - private Map<SampleIdentifier, ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier> getIdMap(List<SampleIdentifier> ids) - { - Map<SampleIdentifier, ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier> sidMap = - new HashMap<SampleIdentifier, ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier>(); - - for (SampleIdentifier id : ids) - { - ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier sid = SampleIdentifierFactory.parse(id.getIdentifier()); - sidMap.put(id, sid); - } - - return sidMap; - } - - private Map<String, SpacePE> getSpaceMap(Collection<ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier> ids) - { - Set<String> spaceCodes = new HashSet<String>(); - - for (ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier id : ids) - { - if (id.isSpaceLevel()) - { - spaceCodes.add(id.getSpaceLevel().getSpaceCode()); - } - } - - if (false == spaceCodes.isEmpty()) - { - List<SpacePE> spaces = spaceDAO.tryFindSpaceByCodes(new ArrayList<String>(spaceCodes)); - Map<String, SpacePE> spaceMap = new HashMap<String, SpacePE>(); - - for (SpacePE space : spaces) - { - spaceMap.put(space.getCode(), space); - } - - return spaceMap; - } else - { - return Collections.emptyMap(); - } - } - - private void addToMap(Map<Key, List<String>> sampleCodesBySpaceAndContainer, SpacePE space, - ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier sampleIdentifier) - { - Key key = new Key(space, sampleIdentifier.tryGetContainerCode()); - List<String> list = sampleCodesBySpaceAndContainer.get(key); - if (list == null) - { - list = new ArrayList<String>(); - sampleCodesBySpaceAndContainer.put(key, list); - } - list.add(sampleIdentifier.getSampleSubCode()); - } - - private static final class Key - { - final SpacePE space; - - final String containerId; - - public Key(SpacePE space, String containerId) - { - super(); - this.space = space; - this.containerId = containerId; - } - - public SpacePE getSpace() - { - return space; - } - - public String getContainerId() - { - return containerId; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((containerId == null) ? 0 : containerId.hashCode()); - result = prime * result + ((space == null) ? 0 : space.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; - Key other = (Key) obj; - if (containerId == null) - { - if (other.containerId != null) - return false; - } else if (!containerId.equals(other.containerId)) - return false; - if (space == null) - { - if (other.space != null) - return false; - } else if (!space.equals(other.space)) - return false; - return true; - } - + return sampleDAO.listByIDs(techIdByIdentifier.listByIds(ids)); } } diff --git a/openbis/sourceTest/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/sample/FullSampleIdentifierTest.java b/openbis/sourceTest/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/sample/FullSampleIdentifierTest.java index a0e592afda4732eb7dc22252ff74f0b071ab27d4..f74dfa8e1e18498a67e58d5f919f9ade3c46f727 100644 --- a/openbis/sourceTest/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/sample/FullSampleIdentifierTest.java +++ b/openbis/sourceTest/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/sample/FullSampleIdentifierTest.java @@ -33,11 +33,15 @@ public class FullSampleIdentifierTest public void testHappyCases() { assertSampId("/S1"); + assertSampId("/C1:S1"); assertSampId("/SPACE1/S2"); assertSampId("/SPACE1/S2:A02"); assertSampId("/SPACE1/PROJECT1/S1"); assertSampId("/SPACE1/PROJECT1/S1:A02"); - + assertSampIdWithHomeSpace("/HS/S1", "//S1", "HS"); + assertSampIdWithHomeSpace("/HS/C1:S1", "//C1:S1", "HS"); + assertSampIdWithHomeSpace("/HS/PROJECT1/S1", "//PROJECT1/S1", "HS"); + assertSampIdWithHomeSpace("/HS/PROJECT1/C1:S1", "//PROJECT1/C1:S1", "HS"); } @Test @@ -53,18 +57,30 @@ public class FullSampleIdentifierTest assertInvalidSampId("Sample identifier don't contain any codes: //", "//"); assertInvalidSampId("Sample identifier don't contain any codes: /", "/"); - assertInvalidSampId("Code field containing other characters than letters, numbers, '_', '-' and '.': S1&*", "/S1&*"); - assertInvalidSampId("Code field containing other characters than letters, numbers, '_', '-' and '.': SPA&CE1", "/SPA&CE1/S2"); - assertInvalidSampId("Code field containing other characters than letters, numbers, '_', '-' and '.': S^2", "/SPACE1/S^2:A02"); - assertInvalidSampId("Code field containing other characters than letters, numbers, '_', '-' and '.': PRO<>JECT1", "/SPACE1/PRO<>JECT1/S1"); - assertInvalidSampId("Code field containing other characters than letters, numbers, '_', '-' and '.': A0(2", "/SPACE1/PROJECT1/S1:A0(2"); + assertInvalidSampId("Space code can not be an empty string.", "//S1"); + assertInvalidSampId("Project code can not be an empty string.", "/S//S1"); + assertInvalidSampId("Sample code starts or ends with ':': /S/:S1", "/S/:S1"); + assertInvalidSampId("Sample code starts or ends with ':': /S/C1:", "/S/C1:"); + assertInvalidSampId("Sample code can not contain more than one ':': /S/C1:S1:", "/S/C1:S1:"); + + String prefix = " containing other characters than letters, numbers, '_', '-' and '.': "; + assertInvalidSampId("Sample code" + prefix + "S1&*", "/S1&*"); + assertInvalidSampId("Space code" + prefix + "SPA&CE1", "/SPA&CE1/S2"); + assertInvalidSampId("Container sample code" + prefix + "S^2", "/SPACE1/S^2:A02"); + assertInvalidSampId("Project code" + prefix + "PRO<>JECT1", "/SPACE1/PRO<>JECT1/S1"); + assertInvalidSampId("Sample subcode" + prefix + "A0(2", "/SPACE1/PROJECT1/S1:A0(2"); } private void assertInvalidSampId(String expectedErrorMsg, String identifier) + { + assertInvalidSampId(expectedErrorMsg, identifier, null); + } + + private void assertInvalidSampId(String expectedErrorMsg, String identifier, String homeSpaceOrNull) { try { - new FullSampleIdentifier(identifier); + new FullSampleIdentifier(identifier, homeSpaceOrNull); fail("IllegalArgumentException expected"); } catch (IllegalArgumentException ex) { @@ -74,7 +90,12 @@ public class FullSampleIdentifierTest private void assertSampId(String identifier) { - assertEquals(new FullSampleIdentifier(identifier).toString(), identifier); + assertEquals(new FullSampleIdentifier(identifier, null).toString(), identifier); + } + + private void assertSampIdWithHomeSpace(String expectedIdentifier, String identifier, String homeSpace) + { + assertEquals(new FullSampleIdentifier(identifier, homeSpace).toString(), expectedIdentifier); } } diff --git a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/api/v3/ProjectSampleTest.java b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/api/v3/ProjectSampleTest.java index 552841cce6494506c82ab05915c2c9cb254bbb9e..04e6bdcde47902394b08b4b934e537dbb858c189 100644 --- a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/api/v3/ProjectSampleTest.java +++ b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/api/v3/ProjectSampleTest.java @@ -34,7 +34,6 @@ import org.springframework.test.context.transaction.TransactionConfiguration; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import ch.ethz.sis.openbis.generic.shared.api.v3.IApplicationServerApi; @@ -48,11 +47,11 @@ import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.space.SpaceCreation; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.project.ProjectFetchOptions; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.sample.SampleFetchOptions; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.entitytype.EntityTypePermId; -import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.experiment.ExperimentPermId; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.experiment.IExperimentId; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.project.IProjectId; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.project.ProjectPermId; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.sample.ISampleId; +import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.sample.SampleIdentifier; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.sample.SamplePermId; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.space.ISpaceId; import ch.ethz.sis.openbis.generic.shared.api.v3.dto.id.space.SpacePermId; @@ -74,18 +73,8 @@ import ch.systemsx.cisd.openbis.systemtest.base.BaseTest; @Test(groups = "project-samples") public class ProjectSampleTest extends BaseTest { - private static final String[] SEARCH_METHODS - = {"testSearchForSamplesWithProject", "testSearchForSamplesWithCodeAndWithProject"}; private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, ProjectSampleTest.class); private static final EntityTypePermId ENTITY_TYPE_UNKNOWN = new EntityTypePermId("UNKNOWN"); - private static final String TEST_USER = "test"; - private static final String PASSWORD = "password"; - - private static final String SYSTEM_USER = "system"; - private static final String NOT_EXISTING_USER = "notexistinguser"; - private static final String TEST_SPACE_USER = "test_space"; - private static final String TEST_POWER_USER_CISD = "test_role"; - private static final String TEST_GROUP_OBSERVER = "observer"; @Autowired protected IApplicationServerApi v3api; @@ -96,11 +85,6 @@ public class ProjectSampleTest extends BaseTest private ProjectPermId project2inSpace1; private ProjectPermId project1InSpace2; private ProjectPermId project2InSpace2; - private ExperimentPermId experimentInProject1InSpace1; - private SamplePermId sharedSample1; - private SamplePermId sharedSample2; - private SamplePermId sample1InSpace1; - private SamplePermId sample2InSpace1; @BeforeClass public void createData() @@ -113,13 +97,8 @@ public class ProjectSampleTest extends BaseTest project2inSpace1 = projects.get(1); project1InSpace2 = createProjects(systemSessionToken, space2, "PROJECT1").get(0); project2InSpace2 = createProjects(systemSessionToken, space2, "PROJECT2").get(0); - experimentInProject1InSpace1 = createExperiments(systemSessionToken, project1inSpace1, "EXP1").get(0); - List<SamplePermId> sharedSamples = createSamples(systemSessionToken, null, null, null, "SHARED1", "SHARED2"); - sharedSample1 = sharedSamples.get(0); - sharedSample2 = sharedSamples.get(1); - List<SamplePermId> spaceSamples = createSamples(systemSessionToken, space1, null, null, "SAMPLE1", "SAMPLE2"); - sample1InSpace1 = spaceSamples.get(0); - sample2InSpace1 = spaceSamples.get(1); + createSamples(systemSessionToken, null, null, null, "SHARED1", "SHARED2"); + createSamples(systemSessionToken, space1, null, null, "SAMPLE1", "SAMPLE2"); createSamples(systemSessionToken, space1, project1inSpace1, null, "SAMPLE3", "SAMPLE4"); createSamples(systemSessionToken, space2, project2InSpace2, null, "SAMPLE5", "SAMPLE6"); waitAtLeastASecond(); // to allow checks on modification time stamps @@ -131,6 +110,7 @@ public class ProjectSampleTest extends BaseTest @Test(enabled = false) public void cleanDatabase() { + // super method deletes samples, experiments and data sets from the database } private List<SpacePermId> createSpaces(String sessionToken, String...spaceCodes) @@ -158,20 +138,6 @@ public class ProjectSampleTest extends BaseTest return v3api.createProjects(sessionToken, newProjects); } - private List<ExperimentPermId> createExperiments(String sessionToken, IProjectId projectId, String...experimentCodes) - { - List<ExperimentCreation> newExperiments = new ArrayList<ExperimentCreation>(); - for (String code : experimentCodes) - { - ExperimentCreation experiment = new ExperimentCreation(); - experiment.setTypeId(ENTITY_TYPE_UNKNOWN); - experiment.setProjectId(projectId); - experiment.setCode(code); - newExperiments.add(experiment); - } - return v3api.createExperiments(sessionToken, newExperiments); - } - private List<SamplePermId> createSamples(String sessionToken, ISpaceId spaceOrNull, IProjectId projectOrNull, IExperimentId experimentOrNull, String...codes) { @@ -190,9 +156,9 @@ public class ProjectSampleTest extends BaseTest } @Test - public void testCreateSampleAndMapSamples() + public void testCreateSampleAndMapSamplesByPermId() { - String sampleCode = createUniqueCode(); + String sampleCode = createUniqueCode("S"); SampleCreation sampleCreation = new SampleCreation(); sampleCreation.setCode(sampleCode); sampleCreation.setTypeId(ENTITY_TYPE_UNKNOWN); @@ -208,10 +174,11 @@ public class ProjectSampleTest extends BaseTest assertEquals(sample.getIdentifier().getIdentifier(), "/SPACE1/PROJECT1/" + sampleCode); assertEquals(sample.getProject().getIdentifier().getIdentifier(), "/SPACE1/PROJECT1"); } + @Test - public void testCreateThreeSamplesWithSameCodeInDifferentProjectOfSameSpace() + public void testCreateThreeSamplesWithSameCodeInDifferentProjectOfSameSpaceAndMapSamplesByIdentifier() { - String sampleCode = createUniqueCode(); + String sampleCode = createUniqueCode("S"); SampleCreation s1 = new SampleCreation(); s1.setCode(sampleCode); s1.setTypeId(ENTITY_TYPE_UNKNOWN); @@ -227,23 +194,56 @@ public class ProjectSampleTest extends BaseTest s3.setTypeId(ENTITY_TYPE_UNKNOWN); s3.setSpaceId(space1); - List<SamplePermId> ids = v3api.createSamples(systemSessionToken, Arrays.asList(s1, s2, s3)); + v3api.createSamples(systemSessionToken, Arrays.asList(s1, s2, s3)); SampleFetchOptions fetchOptions = new SampleFetchOptions(); fetchOptions.withProject(); + List<ISampleId> ids = new ArrayList<>(); + ids.add(new SampleIdentifier("/SPACE1/PROJECT1/" + sampleCode)); + ids.add(new SampleIdentifier("/SPACE1/PROJECT2/" + sampleCode)); + ids.add(new SampleIdentifier("/SPACE1/" + sampleCode)); Map<ISampleId, Sample> samples = v3api.mapSamples(systemSessionToken, ids, fetchOptions); assertEquals(samples.get(ids.get(0)).getProject().getIdentifier().toString(), "/SPACE1/PROJECT1"); assertEquals(samples.get(ids.get(1)).getProject().getIdentifier().toString(), "/SPACE1/PROJECT2"); assertEquals(samples.get(ids.get(2)).getProject(), null); } + + @Test + public void testCreateProjectSampleWithComponent() + { + String sampleCode = createUniqueCode("S"); + SampleCreation s1 = new SampleCreation(); + s1.setCode(sampleCode); + s1.setTypeId(ENTITY_TYPE_UNKNOWN); + s1.setSpaceId(space1); + s1.setProjectId(project1inSpace1); + SamplePermId s1PermId = v3api.createSamples(systemSessionToken, Arrays.asList(s1)).get(0); + SampleCreation s2 = new SampleCreation(); + s2.setCode("A01"); + s2.setTypeId(ENTITY_TYPE_UNKNOWN); + s2.setSpaceId(space1); + s2.setProjectId(project1inSpace1); + s2.setContainerId(s1PermId); + v3api.createSamples(systemSessionToken, Arrays.asList(s2)).get(0); + + SampleFetchOptions fetchOptions = new SampleFetchOptions(); + fetchOptions.withProject(); + fetchOptions.withContainer(); + List<ISampleId> ids = new ArrayList<>(); + ids.add(new SampleIdentifier("/SPACE1/PROJECT1/" + sampleCode)); + ids.add(new SampleIdentifier("/SPACE1/PROJECT1/" + sampleCode + ":A01")); + Map<ISampleId, Sample> samples = v3api.mapSamples(systemSessionToken, ids, fetchOptions); + assertEquals(samples.get(ids.get(0)).getProject().getIdentifier().toString(), "/SPACE1/PROJECT1"); + assertEquals(samples.get(ids.get(1)).getProject().getIdentifier().toString(), "/SPACE1/PROJECT1"); + } @Test public void testAssignSpaceSampleToAProject() { - String sampleCode = createUniqueCode(); + String sampleCode = createUniqueCode("S"); SamplePermId spaceSample = createSamples(systemSessionToken, space1, null, null, sampleCode).get(0); SampleUpdate sampleUpdate = new SampleUpdate(); - sampleUpdate.setSampleId(spaceSample); + sampleUpdate.setSampleId(new SampleIdentifier("/SPACE1/" + sampleCode)); sampleUpdate.setProjectId(project1inSpace1); Date now = new Date(); @@ -264,10 +264,10 @@ public class ProjectSampleTest extends BaseTest @Test public void testAssignProjectSampleToADifferentProjectInTheSameSpace() { - String sampleCode = createUniqueCode(); + String sampleCode = createUniqueCode("S"); SamplePermId spaceSample = createSamples(systemSessionToken, space1, project1inSpace1, null, sampleCode).get(0); SampleUpdate sampleUpdate = new SampleUpdate(); - sampleUpdate.setSampleId(spaceSample); + sampleUpdate.setSampleId(new SampleIdentifier("/SPACE1/PROJECT1/" + sampleCode)); sampleUpdate.setProjectId(project2inSpace1); Date now = new Date(); @@ -288,7 +288,7 @@ public class ProjectSampleTest extends BaseTest @Test public void testAssignProjectSampleToAProjectInADifferentSpace() { - String sampleCode = createUniqueCode(); + String sampleCode = createUniqueCode("S"); SamplePermId spaceSample = createSamples(systemSessionToken, space1, project1inSpace1, null, sampleCode).get(0); SampleUpdate sampleUpdate = new SampleUpdate(); sampleUpdate.setSampleId(spaceSample); @@ -313,7 +313,7 @@ public class ProjectSampleTest extends BaseTest @Test public void testUnassignProjectSampleFromProject() { - String sampleCode = createUniqueCode(); + String sampleCode = createUniqueCode("S"); SamplePermId spaceSample = createSamples(systemSessionToken, space1, project1inSpace1, null, sampleCode).get(0); SampleUpdate sampleUpdate = new SampleUpdate(); sampleUpdate.setSampleId(spaceSample); @@ -390,7 +390,8 @@ public class ProjectSampleTest extends BaseTest creation.setTypeId(ENTITY_TYPE_UNKNOWN); creation.setSpaceId(space1); creation.setProjectId(project2inSpace1); - creation.setExperimentId(experimentInProject1InSpace1); + String expCode = createUniqueCode("E"); + creation.setExperimentId(createExperimentInProject1OfSpace1(expCode)); assertUserFailureException(new IDelegatedAction() { @@ -402,7 +403,7 @@ public class ProjectSampleTest extends BaseTest }, "Sample project must be the same as experiment project. " + "Sample: /SPACE1/SAMPLE_WITH_INCONSISTENT_PROJECT_AND_EXPERIMENT, " + "Project: /SPACE1/PROJECT2, " - + "Experiment: /SPACE1/PROJECT1/EXP1 " + + "Experiment: /SPACE1/PROJECT1/" + expCode + " " + "(Context: [verify experiment for sample SAMPLE_WITH_INCONSISTENT_PROJECT_AND_EXPERIMENT])"); } @@ -410,8 +411,10 @@ public class ProjectSampleTest extends BaseTest @Transactional(propagation = Propagation.NEVER) public void testAssignSpaceSampleToProjectInDifferentSpace() { + String code = createUniqueCode("S"); + ISampleId sampleId = createSamples(systemSessionToken, space1, null, null, code).get(0); final SampleUpdate sampleUpdate = new SampleUpdate(); - sampleUpdate.setSampleId(sample1InSpace1); + sampleUpdate.setSampleId(sampleId); sampleUpdate.setProjectId(project2InSpace2); assertUserFailureException(new IDelegatedAction() @@ -422,17 +425,19 @@ public class ProjectSampleTest extends BaseTest v3api.updateSamples(systemSessionToken, Collections.singletonList(sampleUpdate)); } }, "Sample space must be the same as project space. " - + "Sample: /SPACE1/SAMPLE1, " + + "Sample: /SPACE1/" + code + ", " + "Project: /SPACE2/PROJECT2 " - + "(Context: [verify project for sample SAMPLE1])"); + + "(Context: [verify project for sample " + code + "])"); } @Test @Transactional(propagation = Propagation.NEVER) public void testAssignSampleOfAnExperimentToProjectDifferentToTheExperimentProject() { - String sampleCode = createUniqueCode(); - SamplePermId sample = createSamples(systemSessionToken, space1, null, experimentInProject1InSpace1, sampleCode).get(0); + String sampleCode = createUniqueCode("S"); + String expCode = createUniqueCode("E"); + IExperimentId experiment = createExperimentInProject1OfSpace1(expCode); + SamplePermId sample = createSamples(systemSessionToken, space1, null, experiment, sampleCode).get(0); final SampleUpdate sampleUpdate = new SampleUpdate(); sampleUpdate.setSampleId(sample); sampleUpdate.setProjectId(project2inSpace1); @@ -447,7 +452,7 @@ public class ProjectSampleTest extends BaseTest }, "Sample project must be the same as experiment project. " + "Sample: /SPACE1/" + sampleCode + ", " + "Project: /SPACE1/PROJECT2, " - + "Experiment: /SPACE1/PROJECT1/EXP1 " + + "Experiment: /SPACE1/PROJECT1/" + expCode + " " + "(Context: [verify experiment for sample " + sampleCode + "])"); } @@ -456,8 +461,10 @@ public class ProjectSampleTest extends BaseTest @Transactional(propagation = Propagation.NEVER) public void testAssignSharedSampleToProject() { + String code = createUniqueCode("S"); + ISampleId sharedSample = createSamples(systemSessionToken, null, null, null, code).get(0); final SampleUpdate sampleUpdate = new SampleUpdate(); - sampleUpdate.setSampleId(sharedSample1); + sampleUpdate.setSampleId(sharedSample); sampleUpdate.setProjectId(project1inSpace1); assertUserFailureException(new IDelegatedAction() @@ -468,9 +475,9 @@ public class ProjectSampleTest extends BaseTest v3api.updateSamples(systemSessionToken, Collections.singletonList(sampleUpdate)); } }, "Shared samples cannot be attached to projects. " - + "Sample: /SHARED1, " + + "Sample: /" + code + ", " + "Project: /SPACE1/PROJECT1 " - + "(Context: [verify project for sample SHARED1])"); + + "(Context: [verify project for sample " + code + "])"); } @Test(priority = -1) @@ -583,10 +590,19 @@ public class ProjectSampleTest extends BaseTest assertEquals(renderedReferenceDate.compareTo(renderedActualDate) <= 0, true, renderedActualDate + " > " + renderedReferenceDate); } + + private IExperimentId createExperimentInProject1OfSpace1(String code) + { + ExperimentCreation experiment = new ExperimentCreation(); + experiment.setCode(code); + experiment.setTypeId(ENTITY_TYPE_UNKNOWN); + experiment.setProjectId(project1inSpace1); + return v3api.createExperiments(systemSessionToken, Arrays.asList(experiment)).get(0); + } - private String createUniqueCode() + private String createUniqueCode(String prefix) { - return "S-" + System.currentTimeMillis(); + return prefix + "-" + System.currentTimeMillis(); } private void waitAtLeastASecond()