+++ /dev/null
-package io.github.aloussase;
-
-import jakarta.ws.rs.GET;
-import jakarta.ws.rs.Path;
-import jakarta.ws.rs.Produces;
-import jakarta.ws.rs.core.MediaType;
-
-@Path("/hello")
-public class GreetingResource {
-
- @GET
- @Produces(MediaType.TEXT_PLAIN)
- public String hello() {
- return "Hello from Quarkus REST";
- }
-}
--- /dev/null
+package io.github.aloussase.application.controller;
+
+import io.github.aloussase.domain.service.SearchService;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+
+@Path("/search")
+public class SearchResource {
+
+ private final SearchService searchService;
+
+ public SearchResource(SearchService searchService) {
+ this.searchService = searchService;
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String search() {
+ return "Hello from Quarkus REST";
+ }
+}
--- /dev/null
+package io.github.aloussase.config;
+
+import io.github.aloussase.domain.repository.CompositeSource;
+import io.github.aloussase.domain.service.SearchService;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.ws.rs.Produces;
+
+
+public class AppConfig {
+
+ @Produces
+ @ApplicationScoped
+ public SearchService providesSearchService() {
+ final var cs = new CompositeSource();
+ return new SearchService(cs);
+ }
+
+}
--- /dev/null
+package io.github.aloussase.domain.entity;
+
+public record MastersInfo(
+ String mastersName,
+ String shortDescription,
+ String institution,
+ String infoUrl
+) {
+}
--- /dev/null
+package io.github.aloussase.domain.repository;
+
+import io.github.aloussase.domain.entity.MastersInfo;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A {@link Source} that can invoke multiple other sources.
+ */
+public class CompositeSource implements Source {
+ private List<Source> sources;
+
+ /**
+ * Add a new source.
+ *
+ * @param source The source to add.
+ * @return The {@code CompositeSource} instance for fluent chaining.
+ */
+ public CompositeSource addSource(Source source) {
+ sources.add(source);
+ return this;
+ }
+
+ public List<Source> getSources() {
+ return Collections.unmodifiableList(sources);
+ }
+
+ @Override
+ public List<MastersInfo> search(String query) {
+ // TODO: Parallelize this.
+ return sources
+ .stream()
+ .flatMap(s -> s.search(query).stream())
+ .toList();
+ }
+}
--- /dev/null
+package io.github.aloussase.domain.repository;
+
+public interface LocalSource extends Source {
+}
--- /dev/null
+package io.github.aloussase.domain.repository;
+
+/**
+ * A {@link Source} that works by fetching {@link io.github.aloussase.domain.entity.MastersInfo}
+ * from a third party provider via HTTP.
+ */
+public interface RemoteSource extends Source {
+}
--- /dev/null
+package io.github.aloussase.domain.repository;
+
+import io.github.aloussase.domain.entity.MastersInfo;
+
+import java.util.List;
+
+public interface Source {
+ /**
+ * Search for {@link MastersInfo} using the provided query.
+ *
+ * @param query A query to be interpreted by the implementation
+ * @return A list of masters info that matched the query.
+ */
+ List<MastersInfo> search(String query);
+}
--- /dev/null
+package io.github.aloussase.domain.service;
+
+import io.github.aloussase.domain.entity.MastersInfo;
+import io.github.aloussase.domain.repository.Source;
+
+import java.util.List;
+
+public class SearchService {
+
+ private final Source source;
+
+ public SearchService(Source source) {
+ this.source = source;
+ }
+
+ public List<MastersInfo> search(String query) {
+ return source.search(query);
+ }
+}