Skip to content

Commit

Permalink
Refactor and update tests
Browse files Browse the repository at this point in the history
  • Loading branch information
vietnguyengit committed Dec 3, 2024
1 parent ea2f214 commit eabab6d
Show file tree
Hide file tree
Showing 10 changed files with 107 additions and 61 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package au.org.aodn.ardcvocabs.model;

public enum PathName {
categoryApi,
categoryDetailsApi,
vocabApi,
vocabDetailsApi
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package au.org.aodn.ardcvocabs.service;

import au.org.aodn.ardcvocabs.model.PathName;
import au.org.aodn.ardcvocabs.model.VocabApiPaths;
import au.org.aodn.ardcvocabs.model.VocabModel;

import java.util.List;
import java.util.Map;

public interface ArdcVocabService {
List<VocabModel> getVocabTreeFromArdcByType(VocabApiPaths vocabApiPaths);
Map<String, Map<PathName, String>> getResolvedPathCollection();
List<VocabModel> getVocabTreeFromArdcByType(Map<PathName, String> resolvedPaths);
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package au.org.aodn.ardcvocabs.service;

import au.org.aodn.ardcvocabs.model.ArdcRootPaths;
import au.org.aodn.ardcvocabs.model.PathName;
import au.org.aodn.ardcvocabs.model.VocabApiPaths;
import au.org.aodn.ardcvocabs.model.VocabModel;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;
import jakarta.annotation.PostConstruct;
import lombok.Getter;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
Expand Down Expand Up @@ -36,13 +38,9 @@ public class ArdcVocabServiceImpl implements ArdcVocabService {
protected RetryTemplate retryTemplate;

protected static final String VERSION_REGEX = "^version-\\d+-\\d+$";

@Getter
Map<String, Map<PathName, String>> resolvedPathCollection = new HashMap<>();
protected enum PathName {
categoryApi,
categoryDetailsApi,
vocabApi,
vocabDetailsApi
}

@PostConstruct
public void initialiseVersions() {
Expand Down Expand Up @@ -189,10 +187,10 @@ public ArdcVocabServiceImpl(RestTemplate restTemplate, RetryTemplate retryTempla
this.retryTemplate = retryTemplate;
}

protected VocabModel buildVocabByResourceUri(String vocabUri, String vocabApiBase, VocabApiPaths vocabApiPaths) {
protected VocabModel buildVocabByResourceUri(String vocabUri, String vocabApiBase, Map<PathName, String> resolvedPaths) {
String resourceDetailsApi = vocabUri.contains("_classes")
? resolvedPathCollection.get(vocabApiPaths.name()).get(PathName.categoryDetailsApi)
: resolvedPathCollection.get(vocabApiPaths.name()).get(PathName.vocabDetailsApi);
? resolvedPaths.get(PathName.categoryDetailsApi)
: resolvedPaths.get(PathName.vocabDetailsApi);

String detailsUrl = String.format(vocabApiBase + resourceDetailsApi, vocabUri);

Expand Down Expand Up @@ -222,7 +220,7 @@ protected VocabModel buildVocabByResourceUri(String vocabUri, String vocabApiBas
for (JsonNode j : target.get("narrower")) {
if (!about.apply(j).isEmpty()) {
// recursive call
VocabModel narrowerNode = buildVocabByResourceUri(about.apply(j), vocabApiBase, vocabApiPaths);
VocabModel narrowerNode = buildVocabByResourceUri(about.apply(j), vocabApiBase, resolvedPaths);
if (narrowerNode != null) {
narrowerNodes.add(narrowerNode);
}
Expand All @@ -242,7 +240,7 @@ protected VocabModel buildVocabByResourceUri(String vocabUri, String vocabApiBas
return null;
}

protected <T> VocabModel buildVocabModel(T currentNode, String vocabApiBase, VocabApiPaths vocabApiPaths) {
protected <T> VocabModel buildVocabModel(T currentNode, String vocabApiBase, Map<PathName, String> resolvedPaths) {
String resourceUri = null;

if (currentNode instanceof ObjectNode objectNode) {
Expand All @@ -260,12 +258,12 @@ protected <T> VocabModel buildVocabModel(T currentNode, String vocabApiBase, Voc
throw new IllegalArgumentException("Unsupported node type: " + currentNode.getClass().getName());
}

return buildVocabByResourceUri(resourceUri, vocabApiBase, vocabApiPaths);
return buildVocabByResourceUri(resourceUri, vocabApiBase, resolvedPaths);
}

protected Map<String, List<VocabModel>> getVocabLeafNodes(String vocabApiBase, VocabApiPaths vocabApiPaths) {
protected Map<String, List<VocabModel>> getVocabLeafNodes(String vocabApiBase, Map<PathName, String> resolvedPaths) {
Map<String, List<VocabModel>> results = new HashMap<>();
String url = String.format(vocabApiBase + resolvedPathCollection.get(vocabApiPaths.name()).get(PathName.vocabApi));
String url = String.format(vocabApiBase + resolvedPaths.get(PathName.vocabApi));

while (url != null && !url.isEmpty()) {
try {
Expand All @@ -279,7 +277,7 @@ protected Map<String, List<VocabModel>> getVocabLeafNodes(String vocabApiBase, V
if (isNodeValid.apply(node, "items")) {
for (JsonNode j : node.get("items")) {
// Now we need to construct link to detail resources
String dl = String.format(vocabApiBase + resolvedPathCollection.get(vocabApiPaths.name()).get(PathName.vocabDetailsApi), about.apply(j));
String dl = String.format(vocabApiBase + resolvedPaths.get(PathName.vocabDetailsApi), about.apply(j));
try {
log.debug("getVocabLeafNodes -> {}", dl);
ObjectNode d = retryTemplate.execute(context -> restTemplate.getForObject(dl, ObjectNode.class));
Expand All @@ -304,7 +302,7 @@ protected Map<String, List<VocabModel>> getVocabLeafNodes(String vocabApiBase, V
List<VocabModel> vocabNarrower = new ArrayList<>();
if(target.has("narrower") && !target.get("narrower").isEmpty()) {
for(JsonNode currentNode : target.get("narrower")) {
VocabModel narrowerNode = buildVocabModel(currentNode, vocabApiBase, vocabApiPaths);
VocabModel narrowerNode = buildVocabModel(currentNode, vocabApiBase, resolvedPaths);
if (narrowerNode != null) {
vocabNarrower.add(narrowerNode);
}
Expand All @@ -329,7 +327,7 @@ protected Map<String, List<VocabModel>> getVocabLeafNodes(String vocabApiBase, V
List<VocabModel> completedInternalNodes = new ArrayList<>();
vocab.getNarrower().forEach(currentInternalNode -> {
// rebuild currentInternalNode (no linked leaf nodes) to completedInternalNode (with linked leaf nodes)
VocabModel completedInternalNode = buildVocabModel(currentInternalNode, vocabApiBase, vocabApiPaths);
VocabModel completedInternalNode = buildVocabModel(currentInternalNode, vocabApiBase, resolvedPaths);
if (completedInternalNode != null) {
// each internal node now will have linked narrower nodes (if available)
completedInternalNodes.add(completedInternalNode);
Expand Down Expand Up @@ -368,9 +366,9 @@ protected Map<String, List<VocabModel>> getVocabLeafNodes(String vocabApiBase, V
}

@Override
public List<VocabModel> getVocabTreeFromArdcByType(VocabApiPaths vocabApiPaths) {
Map<String, List<VocabModel>> vocabLeafNodes = getVocabLeafNodes(vocabApiBase, vocabApiPaths);
String url = String.format(vocabApiBase + resolvedPathCollection.get(vocabApiPaths.name()).get(PathName.categoryApi));
public List<VocabModel> getVocabTreeFromArdcByType(Map<PathName, String> resolvedPaths) {
Map<String, List<VocabModel>> vocabLeafNodes = getVocabLeafNodes(vocabApiBase, resolvedPaths);
String url = String.format(vocabApiBase + resolvedPaths.get(PathName.categoryApi));
List<VocabModel> vocabCategoryNodes = new ArrayList<>();
while (url != null && !url.isEmpty()) {
try {
Expand Down Expand Up @@ -398,7 +396,7 @@ public List<VocabModel> getVocabTreeFromArdcByType(VocabApiPaths vocabApiPaths)
Map<String, List<VocabModel>> internalVocabCategoryNodes = new HashMap<>();
if (j.has("narrower") && !j.get("narrower").isEmpty()) {
j.get("narrower").forEach(currentNode -> {
VocabModel internalNode = buildVocabModel(currentNode, vocabApiBase, vocabApiPaths);
VocabModel internalNode = buildVocabModel(currentNode, vocabApiBase, resolvedPaths);
if (internalNode != null) {
List<VocabModel> leafNodes = vocabLeafNodes.getOrDefault(internalNode.getAbout(), Collections.emptyList());
if (!leafNodes.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package au.org.aodn.ardcvocabs.service;

import au.org.aodn.ardcvocabs.BaseTestClass;
import au.org.aodn.ardcvocabs.model.PathName;
import au.org.aodn.ardcvocabs.model.VocabApiPaths;
import au.org.aodn.ardcvocabs.model.VocabModel;
import com.fasterxml.jackson.databind.ObjectMapper;
Expand Down Expand Up @@ -197,27 +198,27 @@ public void init() {
this.ardcVocabService = new ArdcVocabServiceImpl(mockRestTemplate, new RetryTemplate());
this.ardcVocabService.vocabApiBase = "https://vocabs.ardc.edu.au/repository/api/lda/aodn";

Map<String, Map<ArdcVocabServiceImpl.PathName, String>> resolvedPathCollection = new HashMap<>();
Map<String, Map<PathName, String>> resolvedPathCollection = new HashMap<>();

resolvedPathCollection.put(VocabApiPaths.PARAMETER_VOCAB.name(), Map.of(
ArdcVocabServiceImpl.PathName.vocabApi, "/aodn-discovery-parameter-vocabulary/version-1-6/concept.json",
ArdcVocabServiceImpl.PathName.categoryApi, "/aodn-parameter-category-vocabulary/version-2-1/concept.json",
ArdcVocabServiceImpl.PathName.categoryDetailsApi, "/aodn-parameter-category-vocabulary/version-2-1/resource.json?uri=%s",
ArdcVocabServiceImpl.PathName.vocabDetailsApi, "/aodn-discovery-parameter-vocabulary/version-1-6/resource.json?uri=%s"
PathName.vocabApi, "/aodn-discovery-parameter-vocabulary/version-1-6/concept.json",
PathName.categoryApi, "/aodn-parameter-category-vocabulary/version-2-1/concept.json",
PathName.categoryDetailsApi, "/aodn-parameter-category-vocabulary/version-2-1/resource.json?uri=%s",
PathName.vocabDetailsApi, "/aodn-discovery-parameter-vocabulary/version-1-6/resource.json?uri=%s"
));

resolvedPathCollection.put(VocabApiPaths.PLATFORM_VOCAB.name(), Map.of(
ArdcVocabServiceImpl.PathName.vocabApi, "/aodn-platform-vocabulary/version-6-1/concept.json",
ArdcVocabServiceImpl.PathName.categoryApi, "/aodn-platform-category-vocabulary/version-1-2/concept.json",
ArdcVocabServiceImpl.PathName.categoryDetailsApi, "/aodn-platform-category-vocabulary/version-1-2/resource.json?uri=%s",
ArdcVocabServiceImpl.PathName.vocabDetailsApi, "/aodn-platform-vocabulary/version-6-1/resource.json?uri=%s"
PathName.vocabApi, "/aodn-platform-vocabulary/version-6-1/concept.json",
PathName.categoryApi, "/aodn-platform-category-vocabulary/version-1-2/concept.json",
PathName.categoryDetailsApi, "/aodn-platform-category-vocabulary/version-1-2/resource.json?uri=%s",
PathName.vocabDetailsApi, "/aodn-platform-vocabulary/version-6-1/resource.json?uri=%s"
));

resolvedPathCollection.put(VocabApiPaths.ORGANISATION_VOCAB.name(), Map.of(
ArdcVocabServiceImpl.PathName.vocabApi, "/aodn-organisation-vocabulary/version-2-5/concept.json",
ArdcVocabServiceImpl.PathName.categoryApi, "/aodn-organisation-category-vocabulary/version-2-5/concept.json",
ArdcVocabServiceImpl.PathName.categoryDetailsApi, "/aodn-organisation-category-vocabulary/version-2-5/resource.json?uri=%s",
ArdcVocabServiceImpl.PathName.vocabDetailsApi, "/aodn-organisation-vocabulary/version-2-5/resource.json?uri=%s"
PathName.vocabApi, "/aodn-organisation-vocabulary/version-2-5/concept.json",
PathName.categoryApi, "/aodn-organisation-category-vocabulary/version-2-5/concept.json",
PathName.categoryDetailsApi, "/aodn-organisation-category-vocabulary/version-2-5/resource.json?uri=%s",
PathName.vocabDetailsApi, "/aodn-organisation-vocabulary/version-2-5/resource.json?uri=%s"
));

this.ardcVocabService.resolvedPathCollection = resolvedPathCollection;
Expand Down Expand Up @@ -262,7 +263,7 @@ public void verifyParameterVocab() throws IOException, JSONException {

mockRestTemplate = setupParameterVocabMockRestTemplate(mockRestTemplate);

List<VocabModel> parameterVocabModelList = ardcVocabService.getVocabTreeFromArdcByType(VocabApiPaths.PARAMETER_VOCAB);
List<VocabModel> parameterVocabModelList = ardcVocabService.getVocabTreeFromArdcByType(this.ardcVocabService.resolvedPathCollection.get(VocabApiPaths.PARAMETER_VOCAB.name()));
assertEquals(4, parameterVocabModelList.size(), "Total equals");

Optional<VocabModel> c = parameterVocabModelList
Expand Down Expand Up @@ -356,7 +357,7 @@ public void verifyParameterVocab() throws IOException, JSONException {
public void verifyPlatform() throws IOException, JSONException {
mockRestTemplate = setupPlatformMockRestTemplate(mockRestTemplate);

List<VocabModel> platformVocabsFromArdc = ardcVocabService.getVocabTreeFromArdcByType(VocabApiPaths.PLATFORM_VOCAB);
List<VocabModel> platformVocabsFromArdc = ardcVocabService.getVocabTreeFromArdcByType(this.ardcVocabService.resolvedPathCollection.get(VocabApiPaths.PLATFORM_VOCAB.name()));

// verify the contents randomly
assertNotNull(platformVocabsFromArdc);
Expand Down Expand Up @@ -396,7 +397,7 @@ public void verifyPlatform() throws IOException, JSONException {
public void verifyOrganization() throws IOException, JSONException {
mockRestTemplate = setupOrganizationMockRestTemplate(mockRestTemplate);

List<VocabModel> organisationVocabsFromArdc = ardcVocabService.getVocabTreeFromArdcByType(VocabApiPaths.ORGANISATION_VOCAB);
List<VocabModel> organisationVocabsFromArdc = ardcVocabService.getVocabTreeFromArdcByType(this.ardcVocabService.resolvedPathCollection.get(VocabApiPaths.ORGANISATION_VOCAB.name()));

// verify the contents randomly
assertNotNull(organisationVocabsFromArdc);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,23 +65,23 @@ public ResponseEntity<List<JsonNode>> getOrganisationVocabs() throws IOException
@GetMapping(path="/ardc/parameter/vocabs")
@Operation(security = { @SecurityRequirement(name = "X-API-Key") }, description = "Get parameter vocabs from ARDC directly")
public ResponseEntity<List<JsonNode>> getParameterVocabsFromArdc() {
List<VocabModel> vocabs = ardcVocabService.getVocabTreeFromArdcByType(VocabApiPaths.PARAMETER_VOCAB);
List<VocabModel> vocabs = ardcVocabService.getVocabTreeFromArdcByType(ardcVocabService.getResolvedPathCollection().get(VocabApiPaths.PARAMETER_VOCAB.name()));
return ResponseEntity.ok(indexerObjectMapper.valueToTree(vocabs));
}

// this endpoint for debugging/development purposes
@GetMapping(path="/ardc/platform/vocabs")
@Operation(security = { @SecurityRequirement(name = "X-API-Key") }, description = "Get platform vocabs from ARDC directly")
public ResponseEntity<List<JsonNode>> getPlatformVocabsFromArdc() {
List<VocabModel> vocabs = ardcVocabService.getVocabTreeFromArdcByType(VocabApiPaths.PLATFORM_VOCAB);
List<VocabModel> vocabs = ardcVocabService.getVocabTreeFromArdcByType(ardcVocabService.getResolvedPathCollection().get(VocabApiPaths.PLATFORM_VOCAB.name()));
return ResponseEntity.ok(indexerObjectMapper.valueToTree(vocabs));
}

// this endpoint for debugging/development purposes
@GetMapping(path="/ardc/organisation/vocabs")
@Operation(security = { @SecurityRequirement(name = "X-API-Key") }, description = "Get organisation vocabs from ARDC directly")
public ResponseEntity<List<JsonNode>> getOrganisationVocabsFromArdc() {
List<VocabModel> vocabs = ardcVocabService.getVocabTreeFromArdcByType(VocabApiPaths.ORGANISATION_VOCAB);
List<VocabModel> vocabs = ardcVocabService.getVocabTreeFromArdcByType(ardcVocabService.getResolvedPathCollection().get(VocabApiPaths.ORGANISATION_VOCAB.name()));
return ResponseEntity.ok(indexerObjectMapper.valueToTree(vocabs));
}

Expand All @@ -94,7 +94,7 @@ public ResponseEntity<String> populateDataToVocabsIndex() throws IOException, Ex
vocabService.clearPlatformVocabCache();
vocabService.clearOrganisationVocabCache();
// populate new data
vocabService.populateVocabsData();
vocabService.populateVocabsData(ardcVocabService.getResolvedPathCollection());
return ResponseEntity.status(HttpStatus.NO_CONTENT).body("Populated data to the vocabs index");
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
package au.org.aodn.esindexer.service;

import au.org.aodn.ardcvocabs.model.PathName;
import au.org.aodn.ardcvocabs.model.VocabModel;
import au.org.aodn.stac.model.ContactsModel;
import au.org.aodn.stac.model.ThemesModel;
import com.fasterxml.jackson.databind.JsonNode;

import java.io.IOException;
import java.util.List;
import java.util.Map;

public interface VocabService {
List<String> extractVocabLabelsFromThemes(List<ThemesModel> themes, String vocabType) throws IOException;
List<String> extractOrganisationVocabLabelsFromThemes(List<ThemesModel> themes) throws IOException;
List<VocabModel> getMappedOrganisationVocabsFromContacts(List<ContactsModel> contacts) throws IOException;
void populateVocabsData() throws IOException;
void populateVocabsDataAsync();
void populateVocabsData(Map<String, Map<PathName, String>> resolvedPathCollection) throws IOException;
void populateVocabsDataAsync(Map<String, Map<PathName, String>> resolvedPathCollection);
void clearParameterVocabCache();
void clearPlatformVocabCache();
void clearOrganisationVocabCache();
Expand Down
Loading

0 comments on commit eabab6d

Please sign in to comment.