Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor experiment's external resource handling #148

Open
wants to merge 11 commits into
base: develop
Choose a base branch
from

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
package uk.ac.ebi.atlas.experimentpage.link;

import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.util.DefaultUriBuilderFactory;
import org.springframework.web.util.UriBuilder;
import uk.ac.ebi.atlas.model.download.ExternallyAvailableContent;
import uk.ac.ebi.atlas.model.experiment.Experiment;
import uk.ac.ebi.atlas.model.experiment.baseline.BaselineExperiment;
import uk.ac.ebi.atlas.model.experiment.differential.DifferentialExperiment;
import uk.ac.ebi.atlas.model.experiment.differential.microarray.MicroarrayExperiment;
import uk.ac.ebi.atlas.model.experiment.singlecell.SingleCellBaselineExperiment;

import java.net.URI;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.function.Function;
Expand All @@ -23,44 +17,31 @@

@Component
public class LinkToArrayExpress {
// You’ll get a 302 if the last slash is missing!

private final ResourceLinkGenerator resourceLinkGenerator;

public LinkToArrayExpress(ResourceLinkGenerator resourceLinkGenerator) {
this.resourceLinkGenerator = resourceLinkGenerator;
}

private static final UriBuilder BIOSTUDIES_API_URI_BUILDER =
new DefaultUriBuilderFactory().builder()
.scheme("https")
.host("www.ebi.ac.uk")
.pathSegment("biostudies")
.pathSegment("api")
.pathSegment("v1")
.pathSegment("studies")
.pathSegment("{0}");
// You’ll get a 302 if the last slash is missing!
private static final UriBuilder EXPERIMENTS_URI_BUILDER =
new DefaultUriBuilderFactory().builder()
.scheme("https")
.host("www.ebi.ac.uk")
.pathSegment("arrayexpress")
.pathSegment("experiments")
.pathSegment("{0}")
.path("/");
private static final UriBuilder ARRAYS_URI_BUILDER =
new DefaultUriBuilderFactory().builder()
.scheme("https")
.host("www.ebi.ac.uk")
.pathSegment("arrayexpress")
.pathSegment("arrays")
.pathSegment("{0}")
.path("/");
private static final WebClient webClient = WebClient.create();
.pathSegment("{1}");

private static final Function<Experiment, String> formatLabelToExperiment =
private static final Function<Experiment<?>, String> formatLabelToExperiment =
e -> MessageFormat.format("ArrayExpress: experiment {0}", e.getAccession());
private static final Function<String, String> formatLabelToArray =
arrayAccession -> MessageFormat.format("ArrayExpress: array design {0}", arrayAccession);

private static final Function<String, ExternallyAvailableContent.Description> createIcon =
label -> ExternallyAvailableContent.Description.create("icon-ae", label);

private static final Function<Experiment, ExternallyAvailableContent.Description> createIconForExperiment =
private static final Function<Experiment<?>, ExternallyAvailableContent.Description> createIconForExperiment =
formatLabelToExperiment.andThen(createIcon);
private static final Function<String, ExternallyAvailableContent.Description> createIconForArray =
formatLabelToArray.andThen(createIcon);
Expand All @@ -69,21 +50,21 @@ public ExternallyAvailableContent.ContentType contentType() {
return ExternallyAvailableContent.ContentType.SUPPLEMENTARY_INFORMATION;
}

public Collection<ExternallyAvailableContent> get(Experiment experiment) {
public Collection<ExternallyAvailableContent> get(Experiment<?> experiment) {

var externalLinkFromExperiment = Stream.of(experiment.getAccession())
.map(accession -> Pair.of(EXPERIMENTS_URI_BUILDER.build(accession), BIOSTUDIES_API_URI_BUILDER.build(accession)))
.filter(pairOfLinks -> LinkToArrayExpress.isUriValid(pairOfLinks.getRight()))
.map(Pair::getLeft)
.map(accession -> BIOSTUDIES_API_URI_BUILDER.build("studies", accession))
.filter(resourceLinkGenerator::isUriValid)
.map(uri -> new ExternallyAvailableContent(
uri.toString(),
createIconForExperiment.apply(experiment)));
if(experiment.getType().isMicroarray()) {
if (experiment.getType().isMicroarray()) {
return Stream.concat(
externalLinkFromExperiment,
((MicroarrayExperiment) experiment).getArrayDesignAccessions().stream()
.parallel()
.map(accession -> Pair.of(ARRAYS_URI_BUILDER.build(accession), accession))
.filter(uriAccession -> isUriValid(uriAccession.getLeft()))
.map(accession -> Pair.of(BIOSTUDIES_API_URI_BUILDER.build("arrays", accession), accession))
.filter(uriAccession -> resourceLinkGenerator.isUriValid(uriAccession.getLeft()))
.map(uriAccession -> new ExternallyAvailableContent(
uriAccession.getLeft().toString(),
createIconForArray.apply(uriAccession.getRight()))))
Expand All @@ -92,18 +73,4 @@ public Collection<ExternallyAvailableContent> get(Experiment experiment) {

return externalLinkFromExperiment.collect(toImmutableList());
}

private static boolean isUriValid(@NotNull URI uri) {
try {
return !webClient
.get()
.uri(uri)
.exchange()
.block()
.statusCode()
.isError();
} catch (Exception e) {
return false;
}
}
}
16 changes: 11 additions & 5 deletions src/main/java/uk/ac/ebi/atlas/experimentpage/link/LinkToEga.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,24 @@

import java.text.MessageFormat;
import java.util.Collection;
import java.util.Map;
import java.util.function.Function;

import static java.util.Map.entry;

@Component
public class LinkToEga {
private static final UriBuilder EGA_URI_BUILDER =
new DefaultUriBuilderFactory().builder()
.scheme("https")
.host("www.ebi.ac.uk")
.pathSegment("ega")
.pathSegment("studies")
.pathSegment("{0}");
.pathSegment("{0}")
.pathSegment("{1}");
private static final Map<String, String> EGA_RESOURCE_TYPE_MAPPING = Map.ofEntries(
entry("EGAD.*", "datasets"),
entry("EGAS.*", "studies")
);

private static final Function<String, String> formatLabelToEga =
arrayAccession -> MessageFormat.format("EGA: {0}", arrayAccession);
Expand All @@ -33,8 +40,7 @@ public ExternallyAvailableContent.ContentType contentType() {
return ExternallyAvailableContent.ContentType.SUPPLEMENTARY_INFORMATION;
}

public Collection<ExternallyAvailableContent> get(Experiment experiment) {
return GenerateResourceLinks.getLinks(experiment, "EGA.*", EGA_URI_BUILDER, createIconForEga);
public Collection<ExternallyAvailableContent> get(Experiment<?> experiment) {
return new ResourceLinkGenerator().getLinks(experiment, EGA_RESOURCE_TYPE_MAPPING, EGA_URI_BUILDER, createIconForEga);
}

}
17 changes: 11 additions & 6 deletions src/main/java/uk/ac/ebi/atlas/experimentpage/link/LinkToEna.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,24 @@

import java.text.MessageFormat;
import java.util.Collection;
import java.util.Map;
import java.util.function.Function;

import static java.util.Map.entry;

@Component
public class LinkToEna {
private static final UriBuilder ENA_URI_BUILDER =
new DefaultUriBuilderFactory().builder()
.scheme("https")
.host("www.ebi.ac.uk")
.pathSegment("ena")
.pathSegment("data")
.pathSegment("view")
.pathSegment("{0}");
.pathSegment("browser")
.pathSegment("{0}")
.pathSegment("{1}");
private static final Map<String, String> ENA_RESOURCE_TYPE_MAPPING = Map.ofEntries(
entry("[DES]RP.*", "view")
);

private static final Function<String, String> formatLabelToEna =
arrayAccession -> MessageFormat.format("ENA: {0}", arrayAccession);
Expand All @@ -34,8 +40,7 @@ public ExternallyAvailableContent.ContentType contentType() {
return ExternallyAvailableContent.ContentType.SUPPLEMENTARY_INFORMATION;
}

public Collection<ExternallyAvailableContent> get(Experiment experiment) {
return GenerateResourceLinks.getLinks(experiment, "[^G]*", ENA_URI_BUILDER, createIconForEna);
public Collection<ExternallyAvailableContent> get(Experiment<?> experiment) {
return new ResourceLinkGenerator().getLinks(experiment, ENA_RESOURCE_TYPE_MAPPING, ENA_URI_BUILDER, createIconForEna);
}

}
19 changes: 11 additions & 8 deletions src/main/java/uk/ac/ebi/atlas/experimentpage/link/LinkToGeo.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
import org.springframework.web.util.UriBuilder;
import uk.ac.ebi.atlas.model.download.ExternallyAvailableContent;
import uk.ac.ebi.atlas.model.experiment.Experiment;
import uk.ac.ebi.atlas.model.experiment.baseline.BaselineExperiment;
import uk.ac.ebi.atlas.model.experiment.differential.DifferentialExperiment;
import uk.ac.ebi.atlas.model.experiment.differential.microarray.MicroarrayExperiment;
import uk.ac.ebi.atlas.model.experiment.singlecell.SingleCellBaselineExperiment;
import uk.ac.ebi.atlas.model.experiment.sample.ReportsGeneExpression;

import java.text.MessageFormat;
import java.util.Collection;
import java.util.Map;
import java.util.function.Function;

import static java.util.Map.entry;

@Component
public class LinkToGeo {
private static final UriBuilder GEO_URI_BUILDER =
Expand All @@ -22,8 +22,11 @@ public class LinkToGeo {
.host("www.ncbi.nlm.nih.gov")
.pathSegment("geo")
.pathSegment("query")
.pathSegment("acc.cgi")
.queryParam("acc", "{0}");
.pathSegment("{0}")
.queryParam("acc", "{1}");
private static final Map<String, String> GEO_RESOURCE_TYPE_MAPPING = Map.ofEntries(
entry(".*G(SE|DS).*", "acc.cgi")
);

private static final Function<String, String> formatLabelToGeo =
arrayAccession -> MessageFormat.format("GEO: {0}", arrayAccession);
Expand All @@ -38,8 +41,8 @@ public ExternallyAvailableContent.ContentType contentType() {
return ExternallyAvailableContent.ContentType.SUPPLEMENTARY_INFORMATION;
}

public Collection<ExternallyAvailableContent> get(Experiment experiment) {
return GenerateResourceLinks.getLinks(experiment, "GSE.*", GEO_URI_BUILDER, createIconForGeo);
public Collection<ExternallyAvailableContent> get(Experiment<? extends ReportsGeneExpression> experiment) {
return new ResourceLinkGenerator().getLinks(experiment, GEO_RESOURCE_TYPE_MAPPING, GEO_URI_BUILDER, createIconForGeo);
}

}
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
package uk.ac.ebi.atlas.experimentpage.link;

import com.google.common.collect.ImmutableSet;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import uk.ac.ebi.atlas.model.download.ExternallyAvailableContent;
import uk.ac.ebi.atlas.model.experiment.Experiment;
import uk.ac.ebi.atlas.model.experiment.baseline.BaselineExperiment;

import java.text.MessageFormat;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.jetbrains.annotations.NotNull;
import java.util.function.Function;
import java.util.stream.Collectors;

Expand All @@ -24,15 +22,20 @@ public class LinkToPride {
private static final Function<String, ExternallyAvailableContent.Description> createIcon =
formatLabel.andThen(label -> ExternallyAvailableContent.Description.create("icon-pride", label));

public Collection<ExternallyAvailableContent> get(Experiment experiment) {
ImmutableSet<String> secondaryAccessions = experiment.getSecondaryAccessions();
public List<ExternallyAvailableContent> get(Experiment<?> experiment) {
var secondaryAccessions = experiment.getSecondaryAccessions();

if (!secondaryAccessions.isEmpty()) {
if (noSecondaryAccession(secondaryAccessions)) {
return getExternallyAvailableContents(secondaryAccessions);
} else {
return emptyContent();
}
}

private boolean noSecondaryAccession(ImmutableSet<String> secondaryAccessions) {
return secondaryAccessions != null && !secondaryAccessions.isEmpty();
}

@NotNull
private static List<ExternallyAvailableContent> emptyContent() {
return Collections.emptyList();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package uk.ac.ebi.atlas.experimentpage.link;

import com.google.common.collect.ImmutableList;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.util.UriBuilder;
import uk.ac.ebi.atlas.model.download.ExternallyAvailableContent;
import uk.ac.ebi.atlas.model.experiment.Experiment;

import java.net.URI;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;

@Component
public class ResourceLinkGenerator {
private static final WebClient webClient = WebClient.create();

public ImmutableList<ExternallyAvailableContent> getLinks(Experiment<?> experiment,
Map<String, String> resourceTypeMapping,
UriBuilder uriBuilder,
Function<String, ExternallyAvailableContent.Description> createIcon) {
if (noSecondaryAccession(experiment)) {
return ImmutableList.of();
}

return experiment.getSecondaryAccessions().stream()
.map(accession -> getResourceLink(resourceTypeMapping, uriBuilder, createIcon, accession))
.filter(Objects::nonNull)
.collect(ImmutableList.toImmutableList());
}

private ExternallyAvailableContent getResourceLink(Map<String, String> resourceTypeMapping,
UriBuilder uriBuilder,
Function<String, ExternallyAvailableContent.Description> createIcon,
String accession) {
var link = uriBuilder.build(getPathSegment(resourceTypeMapping, accession), accession);
return isUriValid(link) ?
new ExternallyAvailableContent(link.toString(), createIcon.apply(accession)) :
null;
}

private boolean noSecondaryAccession(Experiment<?> experiment) {
return experiment.getSecondaryAccessions() == null || experiment.getSecondaryAccessions().isEmpty();
}

private String getPathSegment(Map<String, String> resourceTypeMapping, String accession) {
return resourceTypeMapping.entrySet().stream()
.filter(entry -> accession.matches(entry.getKey()))
.findFirst()
.map(Map.Entry::getValue)
.orElse("");
}

public boolean isUriValid(URI uri) {
var response = webClient
.get()
.uri(uri)
.exchange()
.block();
return response != null && !response.statusCode().isError();
}
}
Loading