diff --git a/api-openbis-javascript/src/v3/imaging/dto/ImagingDataSetMultiExport.js b/api-openbis-javascript/src/v3/imaging/dto/ImagingDataSetMultiExport.js index 55a2801e0f59081afd8aa7114b379795e73ba6aa..4478070ef38e24f72e5c2849d5f94e1f33b83cee 100644 --- a/api-openbis-javascript/src/v3/imaging/dto/ImagingDataSetMultiExport.js +++ b/api-openbis-javascript/src/v3/imaging/dto/ImagingDataSetMultiExport.js @@ -5,7 +5,8 @@ define([ "stjs", "util/Exceptions" ], function(stjs, exceptions) { prototype['@type'] = 'imaging.dto.ImagingDataSetMultiExport'; constructor.serialVersionUID = 1; prototype.permId = null; - prototype.index = null; + prototype.imageIndex = null; + prototype.previewIndex = null; prototype.config = null; prototype.metadata = null; @@ -15,11 +16,17 @@ define([ "stjs", "util/Exceptions" ], function(stjs, exceptions) { prototype.setPermId = function(permId) { this.permId = permId; }; - prototype.getIndex = function() { - return this.index; + prototype.getImageIndex = function() { + return this.imageIndex; }; - prototype.setIndex = function(index) { - this.index = index; + prototype.setImageIndex = function(imageIndex) { + this.imageIndex = imageIndex; + }; + prototype.getPreviewIndex = function() { + return this.previewIndex; + }; + prototype.setPreviewIndex = function(previewIndex) { + this.previewIndex = previewIndex; }; prototype.getConfig = function() { return this.config; diff --git a/docs/software-developer-documentation/apis/img/semantic-annotations-classic-nomenclature.png b/docs/software-developer-documentation/apis/img/semantic-annotations-classic-nomenclature.png new file mode 100644 index 0000000000000000000000000000000000000000..a5b2957c5d4fd1aa985cd45b6951bfc44d116cc5 Binary files /dev/null and b/docs/software-developer-documentation/apis/img/semantic-annotations-classic-nomenclature.png differ diff --git a/docs/software-developer-documentation/apis/img/semantic-annotations-modern-nomenclature.png b/docs/software-developer-documentation/apis/img/semantic-annotations-modern-nomenclature.png new file mode 100644 index 0000000000000000000000000000000000000000..77de5765c4b13efab8f86531336b9c11892cf1b7 Binary files /dev/null and b/docs/software-developer-documentation/apis/img/semantic-annotations-modern-nomenclature.png differ diff --git a/docs/software-developer-documentation/apis/img/semantic-annotations-openbis-nomenclature.png b/docs/software-developer-documentation/apis/img/semantic-annotations-openbis-nomenclature.png new file mode 100644 index 0000000000000000000000000000000000000000..1b547ea5452fedff0360d079dd3a226e371ea8f4 Binary files /dev/null and b/docs/software-developer-documentation/apis/img/semantic-annotations-openbis-nomenclature.png differ diff --git a/docs/software-developer-documentation/apis/index.rst b/docs/software-developer-documentation/apis/index.rst index 68618580d1776b255f02bf798a1185929cb52620..d845a0f6157d0f0f90c6388bcd0b325ec7e1b737 100644 --- a/docs/software-developer-documentation/apis/index.rst +++ b/docs/software-developer-documentation/apis/index.rst @@ -7,4 +7,5 @@ APIS java-javascript-v3-api python-v3-api matlab-v3-api - personal-access-tokens \ No newline at end of file + personal-access-tokens + semantic-annotations \ No newline at end of file diff --git a/docs/software-developer-documentation/apis/semantic-annotations.md b/docs/software-developer-documentation/apis/semantic-annotations.md new file mode 100644 index 0000000000000000000000000000000000000000..d4f023dec839005d959a9740e6cdd288f142c126 --- /dev/null +++ b/docs/software-developer-documentation/apis/semantic-annotations.md @@ -0,0 +1,486 @@ +# Semantic Annotations + +- Introduction + - Classic Nomenclature + - Modern Nomenclature + - openBIS Nomenclature +- openBIS Implementation : Java Examples + - Use Case 1 : Annotating a Semantic Class corresponds to Annotating an openBIS Type + - Use Case 2 : Annotating a Semantic Class Property corresponds to Annotating an openBIS Property Assignment + - Use Case 3 : Annotating a Semantic Property corresponds to Annotating an openBIS Property + - Search Based on Semantic Annotations + - Helper Class - Semantic API Extensions + +## Introduction +Semantic annotations were created as a means of standardisation to provide interoperability between systems. +Different systems can then name the same kinds of data differently, but providing the same semantic annotations systems could theoretically interoperate. +One of the biggest hurdles to overcome when trying to understand semantic annotations is the nomenclature. There is a plethora of information often using different terms. +We will now introduce the main three nomenclatures to help the reader to familiarise with them. + +Classic Nomenclature +This is typically found in literature. + + + +For reference: http://www.linkeddatatools.com/semantic-web-basics + +Modern Nomenclature +This is typically found in standards. + + + +For reference: https://www.biomedit.ch/rdf/sphn-ontology/sphn/2022/2 + +openBIS Nomenclature +This is typically found in systems or programming languages. + + + +openBIS Implementation : Java Examples + +## Use Case 1 : Annotating a Semantic Class corresponds to Annotating an openBIS Type +openBIS allows you to annotate Types using semantic annotation URIs through the use of its API using SemanticAnnotationCreation. +In the Example below: +The openBIS Sample Type ADMINISTRATIVE_GENDER is annotated with the semantic class AdministrativeGender. +package ch.ethz.sis.pat; + +```java +import ch.ethz.sis.openbis.generic.asapi.v3.IApplicationServerApi; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.SearchResult; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.EntityKind; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.semanticannotation.create.SemanticAnnotationCreation; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.semanticannotation.id.SemanticAnnotationPermId; +import ch.systemsx.cisd.common.spring.HttpInvokerUtils; + +import java.util.List; +import java.util.Map; + +public class MainSemantic { + + private static final String URL = "https://openbis-sis-ci-sprint.ethz.ch/openbis/openbis" + IApplicationServerApi.SERVICE_URL; + private static final int TIMEOUT = 10000; + + private static final String USER = "admin"; + private static final String PASSWORD = "changeit"; + + public static void main(String[] args) { + IApplicationServerApi v3 = HttpInvokerUtils.createServiceStub(IApplicationServerApi.class, URL, TIMEOUT); + String sessionToken = v3.login(USER, PASSWORD); + + System.out.println("sessionToken: " + sessionToken); + + // Creating semantic annotations using helper methods + SemanticAnnotationCreation administrative_gender = ApplicationServerSemanticAPIExtensions.getSemanticSubjectCreation( + EntityKind.SAMPLE, + "ADMINISTRATIVE_GENDER", + "https://biomedit.ch/rdf/sphn-ontology/sphn", + "https://biomedit.ch/rdf/sphn-ontology/sphn/2022/2", + "https://biomedit.ch/rdf/sphn-ontology/sphn#AdministrativeGender"); + + List<SemanticAnnotationPermId> annotations = v3.createSemanticAnnotations(sessionToken, List.of(administrative_gender)); + System.out.println("created annotations: " + annotations); + + v3.logout(sessionToken); + } +} +``` + +## Use Case 2 : Annotating a Semantic Class Property corresponds to Annotating an openBIS Property Assignment +openBIS allows you to annotate Property Assignments using semantic annotation URIs through the use of its API using SemanticAnnotationCreation. +In the Example below: +The openBIS Property Type IDENTIFIER of the Type ADMINISTRATIVE_GENDER is annotated with the semantic property hasIdentifier. +package ch.ethz.sis.pat; + +```java +import ch.ethz.sis.openbis.generic.asapi.v3.IApplicationServerApi; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.SearchResult; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.EntityKind; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.semanticannotation.create.SemanticAnnotationCreation; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.semanticannotation.id.SemanticAnnotationPermId; +import ch.systemsx.cisd.common.spring.HttpInvokerUtils; + +import java.util.List; +import java.util.Map; + +public class MainSemantic { + + private static final String URL = "https://openbis-sis-ci-sprint.ethz.ch/openbis/openbis" + IApplicationServerApi.SERVICE_URL; + private static final int TIMEOUT = 10000; + + private static final String USER = "admin"; + private static final String PASSWORD = "changeit"; + + public static void main(String[] args) { + IApplicationServerApi v3 = HttpInvokerUtils.createServiceStub(IApplicationServerApi.class, URL, TIMEOUT); + String sessionToken = v3.login(USER, PASSWORD); + + System.out.println("sessionToken: " + sessionToken); + SemanticAnnotationCreation identifier = ApplicationServerSemanticAPIExtensions.getSemanticPredicateWithSubjectCreation( + EntityKind.SAMPLE, + "ADMINISTRATIVE_GENDER", + "identifier", + "https://biomedit.ch/rdf/sphn-ontology/sphn", + "https://biomedit.ch/rdf/sphn-ontology/sphn/2022/2", + "https://biomedit.ch/rdf/sphn-ontology/sphn#hasIdentifier"); + List<SemanticAnnotationPermId> annotations = v3.createSemanticAnnotations(sessionToken, List.of(identifier)); + System.out.println("created annotations: " + annotations); + + v3.logout(sessionToken); + } +} +``` + +## Use Case 3 : Annotating a Semantic Property corresponds to Annotating an openBIS Property +Even if less common, sometimes we can be under the need of annotating a predicate without a subject. +openBIS allows you to annotate Property Types without Types using semantic annotation URIs through the use of its API using SemanticAnnotationCreation. +In the Example below: +The openBIS Property Type IDENTIFIER is annotated with the semantic property hasIdentifier. +package ch.ethz.sis.pat; + +```java +import ch.ethz.sis.openbis.generic.asapi.v3.IApplicationServerApi; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.SearchResult; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.EntityKind; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.semanticannotation.create.SemanticAnnotationCreation; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.semanticannotation.id.SemanticAnnotationPermId; +import ch.systemsx.cisd.common.spring.HttpInvokerUtils; + +import java.util.List; +import java.util.Map; + +public class MainSemantic { + + private static final String URL = "https://openbis-sis-ci-sprint.ethz.ch/openbis/openbis" + IApplicationServerApi.SERVICE_URL; + private static final int TIMEOUT = 10000; + + private static final String USER = "admin"; + private static final String PASSWORD = "changeit"; + + public static void main(String[] args) { + IApplicationServerApi v3 = HttpInvokerUtils.createServiceStub(IApplicationServerApi.class, URL, TIMEOUT); + String sessionToken = v3.login(USER, PASSWORD); + + System.out.println("sessionToken: " + sessionToken); + SemanticAnnotationCreation identifierOnly = ApplicationServerSemanticAPIExtensions.getSemanticPredicateCreation( + "identifier", + "https://biomedit.ch/rdf/sphn-ontology/sphn", + "https://biomedit.ch/rdf/sphn-ontology/sphn/2022/2", + "https://biomedit.ch/rdf/sphn-ontology/sphn#hasIdentifier"); + List<SemanticAnnotationPermId> annotations = v3.createSemanticAnnotations(sessionToken, List.of(identifierOnly)); + System.out.println("created annotations: " + annotations); + + v3.logout(sessionToken); + } +} +``` + +## Search Based on Semantic Annotations +openBIS search doesn't directly allow a search based on semantic annotations. This is currently a two steps process. +On the next example we reduce this two step process to a single call for what we believe is the most common use case: Search for subject and predicate of a well known ontology. +We build this example on top of the previous example. We would like now to make a search based on the previously created subject (AdministrativeGender) and predicate (hasIdentifier) to finally obtain Samples having the identifier "12345678". +The reader will appreciate that this search can be done without having previous knowledge of how this semantic annotations map to openBIS types and property types. See example below. +package ch.ethz.sis.pat; + +```java +import ch.ethz.sis.openbis.generic.asapi.v3.IApplicationServerApi; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.SearchResult; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.EntityKind; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.semanticannotation.create.SemanticAnnotationCreation; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.semanticannotation.id.SemanticAnnotationPermId; +import ch.systemsx.cisd.common.spring.HttpInvokerUtils; + +import java.util.List; +import java.util.Map; + +public class MainSemantic { + + private static final String URL = "https://openbis-sis-ci-sprint.ethz.ch/openbis/openbis" + IApplicationServerApi.SERVICE_URL; + private static final int TIMEOUT = 10000; + + private static final String USER = "admin"; + private static final String PASSWORD = "changeit"; + + public static void main(String[] args) { + IApplicationServerApi v3 = HttpInvokerUtils.createServiceStub(IApplicationServerApi.class, URL, TIMEOUT); + String sessionToken = v3.login(USER, PASSWORD); + + System.out.println("sessionToken: " + sessionToken); + + // Searching semantic annotations using helper methods + SearchResult searchResult = ApplicationServerSemanticAPIExtensions.searchEntityWithSemanticAnnotations(v3, sessionToken, + EntityKind.SAMPLE, + "https://biomedit.ch/rdf/sphn-ontology/sphn#AdministrativeGender", + Map.of("https://biomedit.ch/rdf/sphn-ontology/sphn#hasIdentifier", "12345678"), + 0, + Integer.MAX_VALUE + ); + + System.out.println("Found Entities: " + searchResult.getTotalCount()); + v3.logout(sessionToken); + } +} +``` + +## Helper Class - Semantic API Extensions +To facilitate previous straightforward examples we have created the next utility class: +package ch.ethz.sis.pat; + +```java +import ch.ethz.sis.openbis.generic.asapi.v3.IApplicationServerApi; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.fetchoptions.FetchOptions; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.AbstractEntitySearchCriteria; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.SearchResult; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.fetchoptions.DataSetFetchOptions; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.search.DataSetSearchCriteria; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.EntityKind; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.id.EntityTypePermId; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.fetchoptions.ExperimentFetchOptions; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.search.ExperimentSearchCriteria; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.fetchoptions.PropertyAssignmentFetchOptions; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.id.PropertyAssignmentPermId; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.id.PropertyTypePermId; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.fetchoptions.SampleFetchOptions; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.search.SampleSearchCriteria; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.semanticannotation.SemanticAnnotation; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.semanticannotation.create.SemanticAnnotationCreation; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.semanticannotation.fetchoptions.SemanticAnnotationFetchOptions; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.semanticannotation.search.SemanticAnnotationSearchCriteria; +import ch.systemsx.cisd.common.exceptions.UserFailureException; + +import java.util.Map; + +public abstract class ApplicationServerSemanticAPIExtensions { + + /** + * This utility method provides a simplified API to create subject semantic annotations + * + */ + public static SemanticAnnotationCreation getSemanticSubjectCreation( EntityKind subjectEntityKind, + String subjectClass, + String subjectClassOntologyId, + String subjectClassOntologyVersion, + String subjectClassId) { + SemanticAnnotationCreation semanticAnnotationCreation = new SemanticAnnotationCreation(); + // Subject: Type matching an ontology class + semanticAnnotationCreation.setEntityTypeId(new EntityTypePermId(subjectClass, subjectEntityKind)); + // Ontology URL + semanticAnnotationCreation.setPredicateOntologyId(subjectClassOntologyId); + semanticAnnotationCreation.setDescriptorOntologyId(subjectClassOntologyId); + // Ontology Version URL + semanticAnnotationCreation.setPredicateOntologyVersion(subjectClassOntologyVersion); + semanticAnnotationCreation.setDescriptorOntologyVersion(subjectClassOntologyVersion); + // Ontology Class URL + semanticAnnotationCreation.setPredicateAccessionId(subjectClassId); + semanticAnnotationCreation.setDescriptorAccessionId(subjectClassId); + return semanticAnnotationCreation; + } + + /** + * This utility method provides a simplified API to create predicate semantic annotations + * + */ + public static SemanticAnnotationCreation getSemanticPredicateWithSubjectCreation( EntityKind subjectEntityKind, + String subjectClass, + String predicateProperty, + String predicatePropertyOntologyId, + String predicatePropertyOntologyVersion, + String predicatePropertyId) { + SemanticAnnotationCreation semanticAnnotationCreation = new SemanticAnnotationCreation(); + // Subject: Type matching an ontology class + // Predicate: Property matching an ontology class property + semanticAnnotationCreation.setPropertyAssignmentId(new PropertyAssignmentPermId( + new EntityTypePermId(subjectClass, subjectEntityKind), + new PropertyTypePermId(predicateProperty))); + // Ontology URL + semanticAnnotationCreation.setPredicateOntologyId(predicatePropertyOntologyId); + // Ontology Version URL + semanticAnnotationCreation.setPredicateOntologyVersion(predicatePropertyOntologyVersion); + // Ontology Property URL + semanticAnnotationCreation.setPredicateAccessionId(predicatePropertyId); + return semanticAnnotationCreation; + } + + /** + * This utility method provides a simplified API to create predicate semantic annotations + * + */ + public static SemanticAnnotationCreation getSemanticPredicateCreation( String predicateProperty, + String predicatePropertyOntologyId, + String predicatePropertyOntologyVersion, + String predicatePropertyId) { + SemanticAnnotationCreation semanticAnnotationCreation = new SemanticAnnotationCreation(); + // Predicate: Property matching an ontology class property + semanticAnnotationCreation.setPropertyTypeId(new PropertyTypePermId(predicateProperty)); + // Ontology URL + semanticAnnotationCreation.setPredicateOntologyId(predicatePropertyOntologyId); + // Ontology Version URL + semanticAnnotationCreation.setPredicateOntologyVersion(predicatePropertyOntologyVersion); + // Ontology Property URL + semanticAnnotationCreation.setPredicateAccessionId(predicatePropertyId); + return semanticAnnotationCreation; + } + + /** + * This utility method provides a simplified API to search based on semantic subjects and predicates + * + * @throws UserFailureException in case of any problems + */ + public static SearchResult searchEntityWithSemanticAnnotations(IApplicationServerApi v3, + String sessionToken, + EntityKind entityKind, + String subjectClassIDOrNull, + Map<String, String> predicatePropertyIDsOrNull, + Integer fromOrNull, + Integer countOrNull) { + if (entityKind == null) { + throw new UserFailureException("entityKind cannot be null"); + } + if (entityKind == EntityKind.DATA_SET) { + throw new UserFailureException("EntityKind.DATA_SET is not supported"); + } + + // + // Part 1 : Translate semantic classes and properties into openBIS types and property types + // + + SemanticAnnotationSearchCriteria semanticCriteria = new SemanticAnnotationSearchCriteria(); + semanticCriteria.withOrOperator(); + + SemanticAnnotationFetchOptions semanticFetchOptions = new SemanticAnnotationFetchOptions(); + + // Request and collect subjects + if (subjectClassIDOrNull != null) { + semanticCriteria.withPredicateAccessionId().thatEquals(subjectClassIDOrNull); + } + semanticFetchOptions.withEntityType(); + + // Request and collect predicates + if (predicatePropertyIDsOrNull != null) { + for (String predicate : predicatePropertyIDsOrNull.keySet()) { + semanticCriteria.withPredicateAccessionId().thatEquals(predicate); + } + } + PropertyAssignmentFetchOptions propertyAssignmentFetchOptions = semanticFetchOptions.withPropertyAssignment(); + propertyAssignmentFetchOptions.withPropertyType(); + propertyAssignmentFetchOptions.withEntityType(); + + SearchResult<SemanticAnnotation> semanticAnnotationSearchResult = v3.searchSemanticAnnotations(sessionToken, new SemanticAnnotationSearchCriteria(), semanticFetchOptions); + + // + // Part 2 : Create openBIS search matching semantic results + // + + AbstractEntitySearchCriteria criteria = getEntitySearchCriteria(entityKind); + criteria.withAndOperator(); + + // Set Subject + String entityTypeCode = null; + for (SemanticAnnotation semanticAnnotation:semanticAnnotationSearchResult.getObjects()) { + if (semanticAnnotation.getEntityType() != null) { + EntityTypePermId permId = (EntityTypePermId) semanticAnnotation.getEntityType().getPermId(); + if (permId.getEntityKind() == entityKind) { + entityTypeCode = semanticAnnotation.getEntityType().getCode(); + setWithTypeThatEquals(entityKind, criteria, entityTypeCode); + } + } + } + + if (entityTypeCode == null) { + throw new UserFailureException("Entity Type matching Subject not found."); + } + + // Set Predicates matching the Subject + if (predicatePropertyIDsOrNull != null) { + int predicatesFound = 0; + for (SemanticAnnotation semanticAnnotation : semanticAnnotationSearchResult.getObjects()) { + if (semanticAnnotation.getPropertyAssignment() != null && + semanticAnnotation.getPropertyAssignment().getEntityType().getCode().equals(entityTypeCode)) { + EntityTypePermId permId = (EntityTypePermId) semanticAnnotation.getPropertyAssignment().getEntityType().getPermId(); + if (permId.getEntityKind() == entityKind) { + String value = predicatePropertyIDsOrNull.get(semanticAnnotation.getPredicateAccessionId()); + criteria.withProperty(semanticAnnotation.getPropertyAssignment().getPropertyType().getCode()).thatEquals(value); + predicatesFound++; + } + } + } + + if (predicatesFound != predicatePropertyIDsOrNull.size()) { + throw new UserFailureException("Property Types matching Predicates not found."); + } + } + + FetchOptions fetchOptions = getEntityFetchOptions(entityKind); + if (fromOrNull != null) { + fetchOptions.from(fromOrNull); + } + if (countOrNull != null) { + fetchOptions.count(countOrNull); + } + + SearchResult searchResult = getSearchResult(v3, sessionToken, entityKind, criteria, fetchOptions); + return searchResult; + } + + private static void setWithTypeThatEquals(EntityKind entityKind, AbstractEntitySearchCriteria criteria, String entityTypeCode) { + switch (entityKind) { + case EXPERIMENT: + ((ExperimentSearchCriteria) criteria).withType().withCode().thatEquals(entityTypeCode); + break; + case SAMPLE: + ((SampleSearchCriteria) criteria).withType().withCode().thatEquals(entityTypeCode); + break; + case DATA_SET: + ((DataSetSearchCriteria) criteria).withType().withCode().thatEquals(entityTypeCode); + break; + } + } + + private static AbstractEntitySearchCriteria getEntitySearchCriteria(EntityKind entityKind) { + AbstractEntitySearchCriteria criteria = null; + switch (entityKind) { + case EXPERIMENT: + criteria = new ExperimentSearchCriteria(); + break; + case SAMPLE: + criteria = new SampleSearchCriteria(); + break; + case DATA_SET: + criteria = new DataSetSearchCriteria(); + break; + } + return criteria; + } + + private static FetchOptions getEntityFetchOptions(EntityKind entityKind) { + FetchOptions fetchOptions = null; + switch (entityKind) { + case EXPERIMENT: + fetchOptions = new ExperimentFetchOptions(); + break; + case SAMPLE: + fetchOptions = new SampleFetchOptions(); + break; + case DATA_SET: + fetchOptions = new DataSetFetchOptions(); + break; + } + return fetchOptions; + } + + private static SearchResult getSearchResult(IApplicationServerApi v3, String sessionToken, EntityKind entityKind, AbstractEntitySearchCriteria criteria, FetchOptions fetchOptions) { + SearchResult searchResult = null; + switch (entityKind) { + case EXPERIMENT: + searchResult = v3.searchExperiments(sessionToken, (ExperimentSearchCriteria) criteria, (ExperimentFetchOptions) fetchOptions); + break; + case SAMPLE: + searchResult = v3.searchSamples(sessionToken, (SampleSearchCriteria) criteria, (SampleFetchOptions) fetchOptions); + break; + case DATA_SET: + searchResult = v3.searchDataSets(sessionToken, (DataSetSearchCriteria) criteria, (DataSetFetchOptions) fetchOptions); + break; + } + return searchResult; + } +} +``` \ No newline at end of file