Skip to content

Commit

Permalink
Merge pull request #7114 from davidwatkins73/waltz-7099-involvement-t…
Browse files Browse the repository at this point in the history
…ransitive-flag

Involvement transitive flag
  • Loading branch information
jessica-woodland-scott-db authored Jul 16, 2024
2 parents 6862691 + 99464c3 commit 8358d0f
Show file tree
Hide file tree
Showing 14 changed files with 420 additions and 109 deletions.
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
<module>waltz-data</module>
<module>waltz-schema</module>
<module>waltz-test-common</module>
<module>waltz-integration-test</module>
<!--TODO: find a better way of passing a logback configuration file-->
<!--<module>waltz-local-config</module>-->
</modules>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.finos.waltz.schema.tables.Application;
import org.finos.waltz.schema.tables.FlowDiagramEntity;
import org.finos.waltz.schema.tables.Involvement;
import org.finos.waltz.schema.tables.InvolvementKind;
import org.finos.waltz.schema.tables.LogicalFlow;
import org.finos.waltz.schema.tables.MeasurableRating;
import org.finos.waltz.schema.tables.Person;
Expand All @@ -50,19 +51,7 @@
import static org.finos.waltz.common.Checks.checkTrue;
import static org.finos.waltz.model.EntityLifecycleStatus.REMOVED;
import static org.finos.waltz.model.HierarchyQueryScope.EXACT;
import static org.finos.waltz.schema.Tables.APPLICATION_GROUP_OU_ENTRY;
import static org.finos.waltz.schema.Tables.DATABASE_USAGE;
import static org.finos.waltz.schema.Tables.ENTITY_HIERARCHY;
import static org.finos.waltz.schema.Tables.LEGAL_ENTITY_RELATIONSHIP;
import static org.finos.waltz.schema.Tables.ORGANISATIONAL_UNIT;
import static org.finos.waltz.schema.Tables.PHYSICAL_FLOW;
import static org.finos.waltz.schema.Tables.PROCESS_DIAGRAM_ENTITY;
import static org.finos.waltz.schema.Tables.SCENARIO_RATING_ITEM;
import static org.finos.waltz.schema.Tables.SERVER_USAGE;
import static org.finos.waltz.schema.Tables.SOFTWARE_USAGE;
import static org.finos.waltz.schema.Tables.SOFTWARE_VERSION;
import static org.finos.waltz.schema.Tables.SOFTWARE_VERSION_LICENCE;
import static org.finos.waltz.schema.Tables.TAG_USAGE;
import static org.finos.waltz.schema.Tables.*;
import static org.finos.waltz.schema.tables.Application.APPLICATION;
import static org.finos.waltz.schema.tables.ApplicationGroupEntry.APPLICATION_GROUP_ENTRY;
import static org.finos.waltz.schema.tables.EntityRelationship.ENTITY_RELATIONSHIP;
Expand All @@ -83,6 +72,7 @@ public class ApplicationIdSelectorFactory implements Function<IdSelectionOptions

private static final FlowDiagramEntity flowDiagram = FLOW_DIAGRAM_ENTITY.as("fd_aisf");
private static final Involvement involvement = INVOLVEMENT.as("inv_aisf");
private static final InvolvementKind involvementKind = INVOLVEMENT_KIND.as("inv_kind_aisf");
private static final LogicalFlow logicalFlow = LOGICAL_FLOW.as("lf_aisf");
private static final MeasurableRating measurableRating = MEASURABLE_RATING.as("mr_aisf");
private static final Person person = PERSON.as("p_aisf");
Expand Down Expand Up @@ -571,11 +561,13 @@ private Select<Record1<Long>> mkForPersonReportees(IdSelectionOptions options) {
Condition condition = involvement.ENTITY_KIND.eq(EntityKind.APPLICATION.name())
.and(involvement.EMPLOYEE_ID.eq(emp)
.or(involvement.EMPLOYEE_ID.in(reporteeIds)))
.and(applicationConditions);
.and(applicationConditions)
.and(involvementKind.TRANSITIVE.isTrue().or(involvement.EMPLOYEE_ID.eq(emp)));

return DSL
.selectDistinct(involvement.ENTITY_ID)
.from(involvement)
.innerJoin(involvementKind).on(involvementKind.ID.eq(involvement.KIND_ID))
.innerJoin(app)
.on(app.ID.eq(involvement.ENTITY_ID))
.where(condition);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ public class InvolvementKindDao {
.userSelectable(record.getUserSelectable())
.subjectKind(EntityKind.valueOf(record.getSubjectKind()))
.permittedRole(record.getPermittedRole())
.transitive(record.getTransitive())
.build();
};

Expand All @@ -95,6 +96,7 @@ public class InvolvementKindDao {
record.setUserSelectable(ik.userSelectable());
record.setSubjectKind(ik.subjectKind().name());
record.setPermittedRole(ik.permittedRole());
record.setTransitive(ik.transitive());

ik.externalId().ifPresent(record::setExternalId);
ik.id().ifPresent(record::setId);
Expand Down Expand Up @@ -174,6 +176,7 @@ public boolean update(InvolvementKindChangeCommand command) {
command.externalId().ifPresent(change -> record.setExternalId(change.newVal()));
command.userSelectable().ifPresent(change -> record.setUserSelectable(change.newVal()));
command.permittedRole().ifPresent(change -> record.setPermittedRole(change.newVal()));
command.transitive().ifPresent(change -> record.setTransitive(change.newVal()));

UserTimestamp lastUpdate = command.lastUpdate().orElseThrow(() -> new IllegalStateException("InvolvementChangeCommand must have a last update timestamp"));
record.setLastUpdatedAt(Timestamp.valueOf(lastUpdate.at()));
Expand Down Expand Up @@ -216,24 +219,16 @@ public Set<InvolvementKindUsageStat> loadUsageStats() {

return dsl
.with(userStatsCTE)
.select(ik.ID,
ik.NAME,
ik.EXTERNAL_ID,
ik.DESCRIPTION,
entityKindField,
.select(ik.fields())
.select(entityKindField,
personIsRemovedField,
personCountField)
.from(ik)
.leftJoin(userStatsCTE).on(invKindIdField.eq(ik.ID))
.fetch()
.stream()
.collect(groupingBy(
r -> mkRef(
EntityKind.INVOLVEMENT_KIND,
r.get(ik.ID),
r.get(ik.NAME),
r.get(ik.DESCRIPTION),
r.get(ik.EXTERNAL_ID)),
InvolvementKindDao.TO_DOMAIN_MAPPER::map,
mapping(
r -> r.get(entityKindField) == null
? null
Expand Down Expand Up @@ -267,6 +262,12 @@ public InvolvementKindUsageStat loadUsageStatsForKind(Long kindId) {
Involvement inv = INVOLVEMENT;
Person p = PERSON;

InvolvementKind involvementKind = dsl
.select(ik.fields())
.from(ik)
.where(ik.ID.eq(kindId))
.fetchOne(InvolvementKindDao.TO_DOMAIN_MAPPER);

SelectHavingStep<Record4<Long, String, Boolean, Integer>> qry = dsl
.select(ik.ID, inv.ENTITY_KIND, p.IS_REMOVED, DSL.countDistinct(inv.EMPLOYEE_ID).as("person_count"))
.from(inv)
Expand All @@ -285,16 +286,16 @@ public InvolvementKindUsageStat loadUsageStatsForKind(Long kindId) {
? null
: ImmutableStat
.builder()
.entityKind(EntityKind.valueOf(entityKind))
.isCountOfRemovedPeople(r.get(p.IS_REMOVED))
.personCount(r.get("person_count", Integer.class))
.build();
.entityKind(EntityKind.valueOf(entityKind))
.isCountOfRemovedPeople(r.get(p.IS_REMOVED))
.personCount(r.get("person_count", Integer.class))
.build();
})
.filter(Objects::nonNull)
.collect(toSet());

return ImmutableInvolvementKindUsageStat.builder()
.involvementKind(mkRef(EntityKind.INVOLVEMENT_KIND, kindId))
.involvementKind(involvementKind)
.breakdown(statsForKind)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*
* Waltz - Enterprise Architecture
* Copyright (C) 2016, 2017, 2018, 2019 Waltz open source project
* See README.md for more information
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific
*
*/

package org.finos.waltz.integration_test.inmem.service;

import org.finos.waltz.data.application.ApplicationIdSelectorFactory;
import org.finos.waltz.integration_test.inmem.BaseInMemoryIntegrationTest;
import org.finos.waltz.model.EntityKind;
import org.finos.waltz.model.EntityReference;
import org.finos.waltz.model.HierarchyQueryScope;
import org.finos.waltz.model.IdSelectionOptions;
import org.finos.waltz.model.application.Application;
import org.finos.waltz.service.application.ApplicationService;
import org.finos.waltz.test_common.helpers.AppHelper;
import org.finos.waltz.test_common.helpers.InvolvementHelper;
import org.finos.waltz.test_common.helpers.PersonHelper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

import static org.finos.waltz.common.CollectionUtilities.first;
import static org.finos.waltz.common.SetUtilities.asSet;
import static org.finos.waltz.common.SetUtilities.map;
import static org.finos.waltz.model.EntityReference.mkRef;
import static org.finos.waltz.model.IdSelectionOptions.mkOpts;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;


public class InvolvementTest extends BaseInMemoryIntegrationTest {

@Autowired
private AppHelper appHelper;

@Autowired
private PersonHelper personHelper;

@Autowired
private InvolvementHelper involvementHelper;

@Autowired
private ApplicationService appSvc;

@Test
public void directInvolvementsAreFound() {

EntityReference appA = appHelper.createNewApp("a", ouIds.a);
Long personA = personHelper.createPerson("pa");
long ik = involvementHelper.mkInvolvementKind("rel_a");
involvementHelper.createInvolvement(personA, ik, appA);

rebuildHierarchy(EntityKind.PERSON);

IdSelectionOptions opts = mkOpts(
mkRef(EntityKind.PERSON, personA),
HierarchyQueryScope.CHILDREN);

List<Application> apps = appSvc.findByAppIdSelector(opts);
assertEquals("Expected only one app to be found", 1, apps.size());
assertEquals("Should be the app we created earlier", appA, first(apps).entityReference());
}


@Test
public void indirectInvolvementsAreFound() {
EntityReference appA = appHelper.createNewApp("a", ouIds.a);
EntityReference appB = appHelper.createNewApp("b", ouIds.a);
EntityReference appC = appHelper.createNewApp("c", ouIds.a);

Long personA = personHelper.createPerson("pa");
Long personB = personHelper.createPerson("pb");
Long personC = personHelper.createPerson("pc");

personHelper.updateManager(personC, personB);
personHelper.updateManager(personB, personA);

long ik = involvementHelper.mkInvolvementKind("app_rel");
involvementHelper.createInvolvement(personA, ik, appA);
involvementHelper.createInvolvement(personB, ik, appB);
involvementHelper.createInvolvement(personC, ik, appC);

rebuildHierarchy(EntityKind.PERSON);

IdSelectionOptions opts = mkOpts(
mkRef(EntityKind.PERSON, personA),
HierarchyQueryScope.CHILDREN);

List<Application> apps = appSvc.findByAppIdSelector(opts);
assertEquals("Expected only three apps to be found", 3, apps.size());
assertTrue(map(apps, Application::entityReference).containsAll(asSet(appA, appB, appC)));
}


@Test
public void onlyIndirectInvolvementsMarkedAsTransitiveAreFound() {
EntityReference appA1 = appHelper.createNewApp("a1", ouIds.a);
EntityReference appA2 = appHelper.createNewApp("a2", ouIds.a);
EntityReference appB = appHelper.createNewApp("b", ouIds.a);
EntityReference appC1 = appHelper.createNewApp("c1", ouIds.a);
EntityReference appC2 = appHelper.createNewApp("c2", ouIds.a);

Long personA = personHelper.createPerson("pa");
Long personB = personHelper.createPerson("pb");
Long personC = personHelper.createPerson("pc");

personHelper.updateManager(personC, personB);
personHelper.updateManager(personB, personA);

long trans = involvementHelper.mkInvolvementKind("app_rel_trans");
long intrans = involvementHelper.mkInvolvementKind("app_rel_intrans");

involvementHelper.markAsIntransitive(intrans);

involvementHelper.createInvolvement(personA, trans, appA1);
involvementHelper.createInvolvement(personA, intrans, appA2);
involvementHelper.createInvolvement(personB, trans, appB);
involvementHelper.createInvolvement(personC, trans, appC1);
involvementHelper.createInvolvement(personC, intrans, appC2);

rebuildHierarchy(EntityKind.PERSON);

IdSelectionOptions opts = mkOpts(
mkRef(EntityKind.PERSON, personA),
HierarchyQueryScope.CHILDREN);

List<Application> apps = appSvc.findByAppIdSelector(opts);
assertEquals("Expected only four apps to be found", 4, apps.size());
assertTrue("Expecting C2 to be missing, but A2 should be there", map(apps, Application::entityReference).containsAll(asSet(appA1, appA2, appB, appC1)));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,9 @@ public boolean userSelectable() {

@Nullable
public abstract String permittedRole();

@Value.Default
public boolean transitive() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,6 @@ public abstract class InvolvementKindChangeCommand implements EntityChangeComman

public abstract Optional<FieldChange<String>> permittedRole();

public abstract Optional<FieldChange<Boolean>> transitive();

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.finos.waltz.model.EntityKind;
import org.finos.waltz.model.EntityReference;
import org.immutables.value.Value;

import javax.swing.text.html.parser.Entity;
Expand All @@ -24,6 +23,6 @@ public interface Stat {

public abstract Set<Stat> breakdown();

public abstract EntityReference involvementKind();
public abstract InvolvementKind involvementKind();

}
Loading

0 comments on commit 8358d0f

Please sign in to comment.