From 632bdcb871be1777ca59ab1b12bafefe5c6ac562 Mon Sep 17 00:00:00 2001 From: MatheaGjerde Date: Tue, 24 Mar 2026 19:25:06 +0100 Subject: [PATCH] feat: added methods to get organization logos from API --- .../organization/OrganizationService.java | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/src/main/java/edu/group5/app/model/organization/OrganizationService.java b/src/main/java/edu/group5/app/model/organization/OrganizationService.java index c5979f5..9785040 100644 --- a/src/main/java/edu/group5/app/model/organization/OrganizationService.java +++ b/src/main/java/edu/group5/app/model/organization/OrganizationService.java @@ -1,15 +1,28 @@ package edu.group5.app.model.organization; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; + +import java.util.HashMap; import java.util.Map; +import java.util.concurrent.CompletableFuture; /** * Service class for managing organization-related operations. * It interacts with the OrganizationRepository to retrieve organization information * and contains business logic associated with organization management. + * + *

It provides fetching logo URLs by web scraping each organization's page on + * Innsamlingskontrollen.

+ * + * Fetched logo URLs are cached to avoid redundant network requests. */ public class OrganizationService { private OrganizationRepository organizationRepository; + private final Map logoCache = new HashMap<>(); + /** * Constructs an OrganizationService with the given OrganizationRepository. * @param organizationRepository the OrganizationRepository to use for managing organization data; must not be null @@ -55,4 +68,82 @@ public Organization findByOrgNumber(int orgNumber) { public Organization findByOrgName(String name) { return organizationRepository.findByOrgName(name); } + + /** + * Fetches the logo URL for the given page by scraping the {@code div.logo img} + * element. Results are cached so each URL is only fetched once. + * + *

+ * Using Jsoup to web scrape through the URLs in the API. + *

+ * @param pageUrl the URL for the organization's page; may be null or blank + * @return the absolute logo URL, or null if not found or pageUrl is invalid + */ + + public String fetchLogoUrl(String pageUrl) { + if (pageUrl == null || pageUrl.isBlank()) { + return null; + } + + if (logoCache.containsKey(pageUrl)) { + return logoCache.get(pageUrl); + } + + try { + Document doc = Jsoup.connect(pageUrl).get(); + Element img = doc.selectFirst("div.logo img"); + + if (img != null) { + String logoUrl = img.absUrl("src"); + logoCache.put(pageUrl, logoUrl); + return logoUrl; + } + } catch (Exception e) { + System.out.println("Could not get logo for: " + pageUrl); + } + return null; + } + + /** + * Fetches all trusted organizations with their logo URLs. + * + *

+ * For each trusted organization, attempts to get its logo using + * {@link #fetchLogoUrl(String)}. Creates a new Organization + * object including the logo URL. + *

+ * @return a map of trusted organizations keyed by organization number, with logos included + */ + public Map getTrustedOrganizationsWithLogos() { + Map original = getTrustedOrganizations(); + Map trustedOrgsWithLogos = new HashMap<>(); + + for (Organization org : original.values()) { + String logoUrl = fetchLogoUrl(org.websiteUrl()); + + Organization newOrg = new Organization( + org.orgNumber(), + org.name(), + org.trusted(), + org.websiteUrl(), + org.isPreApproved(), + org.description(), + logoUrl + ); + trustedOrgsWithLogos.put(newOrg.orgNumber(), newOrg); + } + return trustedOrgsWithLogos; + } + + /** + * Asynchronously fetches trusted organizations with logos. + * + *

Runs in the background so the UI thread is no blocked. + * Returns a CompletableFuture that completes when all logos are loaded.

+ * + * @return a CompletableFuture containing a map of organizations with logos + */ + public CompletableFuture> getTrustedOrganizationsWithLogosAsync() { + return CompletableFuture.supplyAsync(this::getTrustedOrganizationsWithLogos); + } }