diff --git a/waltz-common/src/main/java/org/finos/waltz/common/ListUtilities.java b/waltz-common/src/main/java/org/finos/waltz/common/ListUtilities.java index f60efc1c80..409b817e1d 100644 --- a/waltz-common/src/main/java/org/finos/waltz/common/ListUtilities.java +++ b/waltz-common/src/main/java/org/finos/waltz/common/ListUtilities.java @@ -195,6 +195,7 @@ public static Optional maybeGet(List xs, int idx) { } } + /** * Given a list, index and default value returns the element at that index or the default value if the index is out of bounds. */ @@ -202,4 +203,15 @@ public static T getOrDefault(List xs, int idx, T defaultValue) { return maybeGet(xs, idx) .orElse(defaultValue); } + + + /** + * Returns a list of distinct values from a given list + * @param ts a list of T's with possible duplicates + * @return distinct values in ts + * @param + */ + public static List distinct(List ts) { + return ts.stream().distinct().collect(toList()); + } } diff --git a/waltz-common/src/test/java/org/finos/waltz/common/ListUtilities_distinct.java b/waltz-common/src/test/java/org/finos/waltz/common/ListUtilities_distinct.java new file mode 100644 index 0000000000..f5108a7637 --- /dev/null +++ b/waltz-common/src/test/java/org/finos/waltz/common/ListUtilities_distinct.java @@ -0,0 +1,20 @@ +package org.finos.waltz.common; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.finos.waltz.common.ListUtilities.asList; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ListUtilities_distinct { + + @Test + public void distinctDedupesListsButPreservesInitialOrder() { + List xs = asList("a", "b", "c", "c", "b", "c", "d"); + List uniq = ListUtilities.distinct(xs); + assertEquals(asList("a", "b", "c", "d"), uniq); + } + + +} diff --git a/waltz-data/src/main/java/org/finos/waltz/data/licence/search/LicenceSearchDao.java b/waltz-data/src/main/java/org/finos/waltz/data/licence/search/LicenceSearchDao.java new file mode 100644 index 0000000000..46d445e3a4 --- /dev/null +++ b/waltz-data/src/main/java/org/finos/waltz/data/licence/search/LicenceSearchDao.java @@ -0,0 +1,70 @@ +package org.finos.waltz.data.licence.search; + +import org.finos.waltz.common.ListUtilities; +import org.finos.waltz.data.SearchDao; +import org.finos.waltz.data.legal_entity.LegalEntityDao; +import org.finos.waltz.data.licence.LicenceDao; +import org.finos.waltz.model.entity_search.EntitySearchOptions; +import org.finos.waltz.model.legal_entity.LegalEntity; +import org.finos.waltz.model.licence.Licence; +import org.jooq.Condition; +import org.jooq.DSLContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.TreeSet; + +import static java.util.Collections.emptyList; +import static org.finos.waltz.common.ListUtilities.concat; +import static org.finos.waltz.data.JooqUtilities.mkBasicTermSearch; +import static org.finos.waltz.data.JooqUtilities.mkStartsWithTermSearch; +import static org.finos.waltz.data.SearchUtilities.mkTerms; +import static org.finos.waltz.schema.Tables.LICENCE; + +@Service +public class LicenceSearchDao implements SearchDao { + + private final DSLContext dsl; + + + @Autowired + public LicenceSearchDao(DSLContext dsl) { + this.dsl = dsl; + } + + + /** + * Searches by name and external_id + * @param options + * @return List of matching legal entities, + * matches on name are given precedence over external_id matches + */ + @Override + public List search(EntitySearchOptions options) { + List terms = mkTerms(options.searchQuery()); + if (terms.isEmpty()) { + return emptyList(); + } + + Condition nameCondition = mkBasicTermSearch(LICENCE.NAME, terms); + Condition externalIdCondition = mkStartsWithTermSearch(LICENCE.EXTERNAL_ID, terms); + + return ListUtilities.distinct(concat( + mkQuery(nameCondition, options), + mkQuery(externalIdCondition, options))); + } + + + private List mkQuery(Condition nameCondition, EntitySearchOptions options) { + return dsl + .select(LICENCE.fields()) + .from(LICENCE) + .where(nameCondition) + .orderBy(LICENCE.NAME) + .limit(options.limit()) + .fetch(LicenceDao.TO_DOMAIN_MAPPER); + } + +} diff --git a/waltz-model/src/main/java/org/finos/waltz/model/licence/Licence.java b/waltz-model/src/main/java/org/finos/waltz/model/licence/Licence.java index b94d4a09f5..20fae24f61 100644 --- a/waltz-model/src/main/java/org/finos/waltz/model/licence/Licence.java +++ b/waltz-model/src/main/java/org/finos/waltz/model/licence/Licence.java @@ -34,5 +34,16 @@ public abstract class Licence implements ExternalIdProvider, CreatedUserTimestampProvider, LastUpdatedUserTimestampProvider, - ProvenanceProvider { + ProvenanceProvider, + WaltzEntity { + + @Override + public EntityReference entityReference() { + return EntityReference.mkRef( + EntityKind.LICENCE, + id().get(), + name(), + description(), + externalId().orElse("")); + } } diff --git a/waltz-ng/client/navbar/components/nav-search-overlay/nav-search-overlay.js b/waltz-ng/client/navbar/components/nav-search-overlay/nav-search-overlay.js index 0cd8f18560..450b6d662d 100644 --- a/waltz-ng/client/navbar/components/nav-search-overlay/nav-search-overlay.js +++ b/waltz-ng/client/navbar/components/nav-search-overlay/nav-search-overlay.js @@ -52,7 +52,8 @@ const initialState = { entity.DATABASE.key, entity.SOFTWARE.key, entity.ROADMAP.key, - entity.LOGICAL_DATA_ELEMENT.key + entity.LOGICAL_DATA_ELEMENT.key, + entity.LICENCE.key ], selectedCategory: null, showActiveOnly: true, @@ -149,7 +150,7 @@ function controller($element, .then(() => handleSearch(query, [entity.APP_GROUP.key, entity.CHANGE_INITIATIVE.key, entity.ORG_UNIT.key])) .then(() => handleSearch(query, [entity.ACTOR.key, entity.MEASURABLE.key, entity.LEGAL_ENTITY.key])) .then(() => handleSearch(query, [entity.PHYSICAL_SPECIFICATION.key, entity.DATA_TYPE.key, entity.SERVER.key, entity.DATABASE.key])) - .then(() => handleSearch(query, [entity.SOFTWARE.key, entity.ROADMAP.key, entity.LOGICAL_DATA_ELEMENT.key])) + .then(() => handleSearch(query, [entity.SOFTWARE.key, entity.ROADMAP.key, entity.LOGICAL_DATA_ELEMENT.key, entity.LICENCE.key])) .catch(e => displayError("Failed to search")) .finally(() => vm.searching = false); }; diff --git a/waltz-service/src/main/java/org/finos/waltz/service/entity_search/EntitySearchService.java b/waltz-service/src/main/java/org/finos/waltz/service/entity_search/EntitySearchService.java index 7fc571fd2b..974b0e5ef8 100644 --- a/waltz-service/src/main/java/org/finos/waltz/service/entity_search/EntitySearchService.java +++ b/waltz-service/src/main/java/org/finos/waltz/service/entity_search/EntitySearchService.java @@ -26,6 +26,7 @@ import org.finos.waltz.service.database_information.DatabaseInformationService; import org.finos.waltz.service.flow_diagram.FlowDiagramService; import org.finos.waltz.service.legal_entity.LegalEntityService; +import org.finos.waltz.service.licence.LicenceService; import org.finos.waltz.service.logical_data_element.LogicalDataElementService; import org.finos.waltz.service.measurable.MeasurableService; import org.finos.waltz.service.orgunit.OrganisationalUnitService; @@ -74,6 +75,7 @@ public class EntitySearchService { private final FlowDiagramService flowDiagramService; private final LegalEntityService legalEntityService; private final DatabaseInformationService databaseInformationService; + private final LicenceService licenceService; @Autowired @@ -93,7 +95,8 @@ public EntitySearchService(DBExecutorPoolInterface dbExecutorPool, SoftwareCatalogService softwareCatalogService, FlowDiagramService flowDiagramService, LegalEntityService legalEntityService, - DatabaseInformationService databaseInformationService) { + DatabaseInformationService databaseInformationService, + LicenceService licenceService) { checkNotNull(dbExecutorPool, "dbExecutorPool cannot be null"); checkNotNull(actorService, "actorService cannot be null"); @@ -112,6 +115,7 @@ public EntitySearchService(DBExecutorPoolInterface dbExecutorPool, checkNotNull(softwareCatalogService, "softwareCatalogService cannot be null"); checkNotNull(legalEntityService, "legalEntityService cannot be null"); checkNotNull(databaseInformationService, "databaseInformationService cannot be null"); + checkNotNull(licenceService, "licenceService cannot be null"); this.actorService = actorService; this.dbExecutorPool = dbExecutorPool; @@ -130,6 +134,7 @@ public EntitySearchService(DBExecutorPoolInterface dbExecutorPool, this.softwareCatalogService = softwareCatalogService; this.legalEntityService = legalEntityService; this.databaseInformationService = databaseInformationService; + this.licenceService = licenceService; } @@ -174,6 +179,8 @@ private Callable> mkCallable(EntityKind entity return () -> flowDiagramService.search(options); case LEGAL_ENTITY: return () -> legalEntityService.search(options); + case LICENCE: + return () -> licenceService.search(options); case LOGICAL_DATA_ELEMENT: return () -> logicalDataElementService.search(options); case MEASURABLE: diff --git a/waltz-service/src/main/java/org/finos/waltz/service/licence/LicenceService.java b/waltz-service/src/main/java/org/finos/waltz/service/licence/LicenceService.java index c59e09276d..bb7d0ce2ba 100644 --- a/waltz-service/src/main/java/org/finos/waltz/service/licence/LicenceService.java +++ b/waltz-service/src/main/java/org/finos/waltz/service/licence/LicenceService.java @@ -21,7 +21,9 @@ import org.finos.waltz.data.licence.LicenceDao; import org.finos.waltz.data.licence.LicenceIdSelectorFactory; +import org.finos.waltz.data.licence.search.LicenceSearchDao; import org.finos.waltz.model.IdSelectionOptions; +import org.finos.waltz.model.entity_search.EntitySearchOptions; import org.finos.waltz.model.licence.Licence; import org.finos.waltz.model.licence.SaveLicenceCommand; import org.finos.waltz.model.tally.Tally; @@ -30,6 +32,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.util.Collection; import java.util.List; import static org.finos.waltz.common.Checks.checkNotNull; @@ -38,13 +41,17 @@ public class LicenceService { private final LicenceDao licenceDao; + private final LicenceSearchDao licenceSearchDao; private final LicenceIdSelectorFactory licenceIdSelectorFactory = new LicenceIdSelectorFactory(); @Autowired - public LicenceService(LicenceDao licenceDao) { + public LicenceService(LicenceDao licenceDao, + LicenceSearchDao licenceSearchDao) { checkNotNull(licenceDao, "licenceDao cannot be null"); + checkNotNull(licenceSearchDao, "licenceSearchDao cannot be null"); this.licenceDao = licenceDao; + this.licenceSearchDao = licenceSearchDao; } @@ -81,4 +88,8 @@ public boolean save(SaveLicenceCommand cmd, String username) { public boolean remove(long licenceId, String username) { return licenceDao.remove(licenceId); } + + public Collection search(EntitySearchOptions options) { + return licenceSearchDao.search(options); + } }