diff --git a/avni-server-api/src/main/java/org/avni/server/dao/metabase/DatabaseRepository.java b/avni-server-api/src/main/java/org/avni/server/dao/metabase/DatabaseRepository.java index f57e0d05b..c419f822f 100644 --- a/avni-server-api/src/main/java/org/avni/server/dao/metabase/DatabaseRepository.java +++ b/avni-server-api/src/main/java/org/avni/server/dao/metabase/DatabaseRepository.java @@ -8,6 +8,8 @@ import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.stereotype.Repository; import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.ArrayList; import java.util.List; @Repository @@ -47,6 +49,27 @@ public Database getDatabaseByName(Database database) { } } + public List getExistingCollectionItems(int collectionId) { + String url = metabaseApiUrl + "/collection/" + collectionId + "/items"; + String jsonResponse = getForObject(url, String.class); + + try { + JsonNode rootNode = objectMapper.readTree(jsonResponse); + JsonNode dataArray = rootNode.path("data"); + + List items = new ArrayList<>(); + for (JsonNode itemNode : dataArray) { + CollectionItem item = new CollectionItem(); + item.setName(itemNode.get("name").asText()); + item.setId(itemNode.get("id").asInt()); + items.add(item); + } + return items; + } catch (Exception e) { + throw new RuntimeException("Failed to fetch collection items", e); + } + } + public CollectionInfoResponse getCollectionByName(Database database) { String url = metabaseApiUrl + "/collection"; try { diff --git a/avni-server-api/src/main/java/org/avni/server/domain/metabase/CollectionItem.java b/avni-server-api/src/main/java/org/avni/server/domain/metabase/CollectionItem.java new file mode 100644 index 000000000..c19a70571 --- /dev/null +++ b/avni-server-api/src/main/java/org/avni/server/domain/metabase/CollectionItem.java @@ -0,0 +1,25 @@ +package org.avni.server.domain.metabase; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CollectionItem { + private String name; + private int id; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } +} diff --git a/avni-server-api/src/main/java/org/avni/server/domain/metabase/FieldAttribute.java b/avni-server-api/src/main/java/org/avni/server/domain/metabase/FieldAttribute.java index e74428016..c00910731 100644 --- a/avni-server-api/src/main/java/org/avni/server/domain/metabase/FieldAttribute.java +++ b/avni-server-api/src/main/java/org/avni/server/domain/metabase/FieldAttribute.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; public enum FieldAttribute { + ALL("all"), FIELD("field"), FIELDS("fields"), SOURCE_TABLE("source-table"), diff --git a/avni-server-api/src/main/java/org/avni/server/domain/metabase/MetabaseQueryBuilder.java b/avni-server-api/src/main/java/org/avni/server/domain/metabase/MetabaseQueryBuilder.java index 2f9ed77d3..1997cb8ec 100644 --- a/avni-server-api/src/main/java/org/avni/server/domain/metabase/MetabaseQueryBuilder.java +++ b/avni-server-api/src/main/java/org/avni/server/domain/metabase/MetabaseQueryBuilder.java @@ -24,7 +24,7 @@ public MetabaseQueryBuilder forTable(TableDetails tableDetails) { public MetabaseQueryBuilder joinWith(TableDetails addressTable, FieldDetails joinField1, FieldDetails joinField2) { ObjectNode joinNode = objectMapper.createObjectNode(); - joinNode.put(FieldAttribute.FIELDS.getAttributeName(), "all"); + joinNode.put(FieldAttribute.FIELDS.getAttributeName(), FieldAttribute.ALL.getAttributeName()); joinNode.put(FieldAttribute.ALIAS.getAttributeName(), addressTable.getName()); ArrayNode conditionArray = objectMapper.createArrayNode(); diff --git a/avni-server-api/src/main/java/org/avni/server/service/metabase/AddressQuestionCreationService.java b/avni-server-api/src/main/java/org/avni/server/service/metabase/AddressQuestionCreationService.java deleted file mode 100644 index 1e2441dda..000000000 --- a/avni-server-api/src/main/java/org/avni/server/service/metabase/AddressQuestionCreationService.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.avni.server.service.metabase; - -import org.avni.server.dao.metabase.DatabaseRepository; -import org.avni.server.domain.metabase.*; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; -import org.springframework.stereotype.Service; - -@Service -public class AddressQuestionCreationService implements QuestionCreationService { - - private final DatabaseService databaseService; - private final DatabaseRepository databaseRepository; - - @Autowired - public AddressQuestionCreationService(@Lazy DatabaseService databaseService, DatabaseRepository databaseRepository) { - this.databaseService = databaseService; - this.databaseRepository = databaseRepository; - } - - @Override - public void createQuestionForTable(TableDetails tableDetails, TableDetails addressTableDetails, FieldDetails addressFieldDetails, FieldDetails tableFieldDetails) { - Database database = databaseService.getGlobalDatabase(); - databaseRepository.createQuestionForTable(database, tableDetails, addressTableDetails, addressFieldDetails, tableFieldDetails); - } - - @Override - public void createQuestionForTable(String tableName, String schema) { - Database database = databaseService.getGlobalDatabase(); - - TableDetails tableDetails = new TableDetails(); - tableDetails.setName(tableName); - TableDetails fetchedTableDetails = databaseRepository.findTableDetailsByName(database, tableDetails); - - databaseRepository.createQuestionForASingleTable(database, fetchedTableDetails); - } -} diff --git a/avni-server-api/src/main/java/org/avni/server/service/metabase/DatabaseService.java b/avni-server-api/src/main/java/org/avni/server/service/metabase/DatabaseService.java index b3e7dca63..fd3cec2e6 100644 --- a/avni-server-api/src/main/java/org/avni/server/service/metabase/DatabaseService.java +++ b/avni-server-api/src/main/java/org/avni/server/service/metabase/DatabaseService.java @@ -7,21 +7,21 @@ import java.util.Arrays; import java.util.ArrayList; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; @Service -public class DatabaseService { +public class DatabaseService implements QuestionCreationService{ private final DatabaseRepository databaseRepository; private final MetabaseService metabaseService; - private final AddressQuestionCreationService addressQuestionCreationService; private static final String ADDRESS_TABLE = "Address"; @Autowired - public DatabaseService(DatabaseRepository databaseRepository, MetabaseService metabaseService, AddressQuestionCreationService addressQuestionCreationService) { + public DatabaseService(DatabaseRepository databaseRepository, MetabaseService metabaseService) { this.databaseRepository = databaseRepository; this.metabaseService = metabaseService; - this.addressQuestionCreationService = addressQuestionCreationService; } public Database getGlobalDatabase() { @@ -45,6 +45,33 @@ private void ensureSyncComplete() { } } + private List filterOutExistingQuestions(List entityNames) { + Set existingItemNames = databaseRepository.getExistingCollectionItems(getGlobalCollection().getIdAsInt()).stream() + .map(item -> item.getName().trim().toLowerCase().replace(" ", "_")) + .collect(Collectors.toSet()); + + return entityNames.stream() + .filter(entityName -> !existingItemNames.contains(entityName.toLowerCase())) + .collect(Collectors.toList()); + } + + @Override + public void createQuestionForTable(TableDetails tableDetails, TableDetails addressTableDetails, FieldDetails addressFieldDetails, FieldDetails tableFieldDetails) { + Database database = getGlobalDatabase(); + databaseRepository.createQuestionForTable(database, tableDetails, addressTableDetails, addressFieldDetails, tableFieldDetails); + } + + @Override + public void createQuestionForTable(String tableName, String schema) { + Database database = getGlobalDatabase(); + + TableDetails tableDetails = new TableDetails(); + tableDetails.setName(tableName); + TableDetails fetchedTableDetails = databaseRepository.findTableDetailsByName(database, tableDetails); + + databaseRepository.createQuestionForASingleTable(database, fetchedTableDetails); + } + public List getSubjectTypeNames() { TableDetails fetchedMetadataTable = databaseRepository.findTableDetailsByName(getGlobalDatabase(), new TableDetails("table_metadata")); @@ -86,49 +113,42 @@ public List getProgramAndEncounterNames() { return programNames; } - public void createQuestionsForSubjectTypes(){ + private void createQuestionsForEntities(List entityNames, FieldDetails addressFieldDetails, FieldDetails entityFieldDetails) { ensureSyncComplete(); - List subjectTypeNames = getSubjectTypeNames(); + TableDetails fetchedAddressTableDetails = databaseRepository.findTableDetailsByName(getGlobalDatabase(), new TableDetails(ADDRESS_TABLE)); + + List filteredEntities = filterOutExistingQuestions(entityNames); - TableDetails addressTableDetails = new TableDetails(ADDRESS_TABLE); - TableDetails fetchedAddressTableDetails = databaseRepository.findTableDetailsByName(getGlobalDatabase(), addressTableDetails); + for (String entityName : filteredEntities) { + TableDetails entityTableDetails = new TableDetails(); + entityTableDetails.setName(entityName); + TableDetails fetchedEntityTableDetails = databaseRepository.findTableDetailsByName(getGlobalDatabase(), entityTableDetails); + createQuestionForTable(fetchedEntityTableDetails, fetchedAddressTableDetails, addressFieldDetails, entityFieldDetails); + } + } + public void createQuestionsForSubjectTypes() { + List subjectTypeNames = getSubjectTypeNames(); FieldDetails addressFieldDetails = new FieldDetails("id"); FieldDetails subjectFieldDetails = new FieldDetails("address_id"); - - - for (String subjectTypeName : subjectTypeNames) { - TableDetails subjectTableDetails = new TableDetails(); - subjectTableDetails.setName(subjectTypeName); - TableDetails fetchedSubjectTableDetails = databaseRepository.findTableDetailsByName(getGlobalDatabase(), subjectTableDetails); - addressQuestionCreationService.createQuestionForTable(fetchedSubjectTableDetails, fetchedAddressTableDetails, addressFieldDetails, subjectFieldDetails); - } + createQuestionsForEntities(subjectTypeNames, addressFieldDetails, subjectFieldDetails); } - public void createQuestionsForProgramsAndEncounters(){ - ensureSyncComplete(); + public void createQuestionsForProgramsAndEncounters() { List programAndEncounterNames = getProgramAndEncounterNames(); - - TableDetails fetchedAddressTableDetails = databaseRepository.findTableDetailsByName(getGlobalDatabase(), new TableDetails(ADDRESS_TABLE)); - FieldDetails addressFieldDetails = new FieldDetails("id"); - FieldDetails programFieldDetails = new FieldDetails("address_id"); - - for (String programName : programAndEncounterNames) { - TableDetails programTableDetails = new TableDetails(); - programTableDetails.setName(programName); - TableDetails fetchedProgramTableDetails = databaseRepository.findTableDetailsByName(getGlobalDatabase(), programTableDetails); - addressQuestionCreationService.createQuestionForTable(fetchedProgramTableDetails, fetchedAddressTableDetails, addressFieldDetails, programFieldDetails); - } + FieldDetails programOrEncounterFieldDetails = new FieldDetails("address_id"); + createQuestionsForEntities(programAndEncounterNames, addressFieldDetails, programOrEncounterFieldDetails); } - public void createQuestionsForIndividualTables(){ + public void createQuestionsForIndividualTables() { ensureSyncComplete(); - List individualTables = Arrays.asList("address", "media", "sync_telemetry"); - for (String tableName : individualTables) { - addressQuestionCreationService.createQuestionForTable(tableName, "!public"); + List filteredTables = filterOutExistingQuestions(individualTables); + + for (String tableName : filteredTables) { + createQuestionForTable(tableName, "!public"); } }