ProductAreaMemberAccumulator.java
package no.nav.data.team.po;
import no.nav.data.team.po.domain.PaMember;
import no.nav.data.team.team.domain.Role;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class ProductAreaMemberAccumulator {
private final Map<String,Item> members;
private ProductAreaMemberAccumulator() {
this.members = new HashMap<>();
}
private synchronized void accumulateMemberRole(String memberNavident, Role memberRole){
var maybeMember = this.members.get(memberNavident);
if(maybeMember == null){
var newItem = new Item(null,Set.of(memberRole));
this.members.put(memberNavident, newItem);
}else{
var item = this.members.get(memberNavident);
item.roles.add(memberRole);
}
}
private void accumulateMemberRole(String memberNavident, List<Role> memberRole){
for(var role : memberRole){
accumulateMemberRole(memberNavident, role);
}
}
public static ProductAreaMemberAccumulator accumulate(
Original original,
Updated updated,
Organizational organizational
) {
if(organizational == null){
throw new IllegalStateException("Cannot update when org data is unavailable");
// return accumulateWithoutOrg(original, updated);
}else{
return accumulateWithOrg(original,updated,organizational);
}
}
private static ProductAreaMemberAccumulator accumulateWithOrg(Original original, Updated updated, Organizational organizational){
var ledereToRoleMap = organizational.ledereToOrgNamesMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> {
var orgenhetNavnList = entry.getValue();
var isFagdirektor = orgenhetNavnList.stream().anyMatch(it -> it.toLowerCase().startsWith("fagdirektør"));
var isPersonalOgBemanningsAnsvarlig = orgenhetNavnList.stream().anyMatch(it -> it.toLowerCase().startsWith("kompetanse"));
return isFagdirektor ? Role.DISCIPLINE_DIRECTOR : isPersonalOgBemanningsAnsvarlig ? Role.PERSONELLROSTER_RESPONSIBLE : Role.DISCIPLINE_AND_DELIVERY_MANAGER;
}));
var out = new ProductAreaMemberAccumulator();
if(updated.memberList == null){
out.accumulateMemberRoleList(original.memberList);
out.purgeMemberRoles(Role.getLeadergroupRoles());
}else{
out.accumulateMemberRoleList(updated.memberList);
}
out.accumulateMemberRole(organizational.lederNavIdent, Role.LEADER);
for (Map.Entry<String, Role> entry : ledereToRoleMap.entrySet()) {
String navident = entry.getKey();
Role role = entry.getValue();
var gotLeder = organizational.lederNavIdent.equals(navident);
if (!gotLeder) {
out.accumulateMemberRole(navident, role);
}
}
for (String customOwnerNavIdent : updated.ownerGroupList()) {
if (ledereToRoleMap.containsKey(customOwnerNavIdent)) {
throw new IllegalArgumentException("Cannot add custom owner " + customOwnerNavIdent + " when this navident is already owner through organization structure");
}
out.accumulateMemberRole(customOwnerNavIdent, Role.DISCIPLINE_AND_DELIVERY_MANAGER);
}
return out;
}
private void purgeMemberRoles(List<Role> leadergroupRoles) {
this.members.values().forEach(item -> {
item.roles.removeAll(leadergroupRoles);
});
}
private static ProductAreaMemberAccumulator accumulateWithoutOrg(Original original, Updated updated){
var out = new ProductAreaMemberAccumulator();
if(updated.memberList == null){
out.accumulateMemberRoleList(original.memberList);
}else{
var originalLeaders = original.memberList.stream().filter(it -> it.getRoles().stream().anyMatch(Role::isLeaderGroupRole)).toList();
out.accumulateMemberRoleList(originalLeaders);
out.purgeMemberRoles(Role.getNonLeadergroupRoles());
out.accumulateMemberRoleList(updated.memberList);
}
return out;
}
private void accumulateMemberRoleList(List<PaMember> memberList) {
for(var member : memberList){
this.accumulateMemberRole(member.getNavIdent(),member.getRoles());
var descriptionTarget = this.members.get(member.getNavIdent());
descriptionTarget.description = member.getDescription();
}
}
public List<PaMember> membersToPersist() {
var tmp = this.members.entrySet().stream()
.map(itemEntry -> new PaMember(itemEntry.getKey(), itemEntry.getValue().roles.stream().toList(), itemEntry.getValue().description))
.filter(it -> !it.getRoles().isEmpty())
.toList();
return new ArrayList<>(tmp);
}
private static final class Item {
private String description;
private final Set<Role> roles;
public Item(String description, Set<Role> roles) {
this.roles = new HashSet<>(roles);
this.description = description;
}
}
public record Original(List<PaMember> memberList, List<String> ownerGroupList){}
public record Updated(List<PaMember> memberList, List<String> ownerGroupList){
public Updated(List<PaMember> memberList, List<String> ownerGroupList){
this.memberList = memberList;
this.ownerGroupList = ownerGroupList == null ? List.of() : ownerGroupList;
if(this.memberList != null){
var membersWithLeaderGroupRoles = this.memberList().stream().filter(x -> x.getRoles().stream().anyMatch(Role::isLeaderGroupRole)).toList();
if(!membersWithLeaderGroupRoles.isEmpty()){
var culprits = membersWithLeaderGroupRoles.stream().map(PaMember::getNavIdent).collect(Collectors.joining(", "));
throw new IllegalArgumentException("Cannot assign leader roles for regular members: " + culprits);
}
}
}
}
public record Organizational(String lederNavIdent, Map<String, List<String>> ledereToOrgNamesMap) {
public Organizational {
assertAllLedereInMap(lederNavIdent, ledereToOrgNamesMap);
}
private static void assertAllLedereInMap(String lederNavident, Map<String, List<String>> ledereOrgEnhetNavnMap) {
var hasKey = ledereOrgEnhetNavnMap.containsKey(lederNavident);
var hasValue = ledereOrgEnhetNavnMap.get(lederNavident) != null;
var hasNames = hasValue && !ledereOrgEnhetNavnMap.get(lederNavident).isEmpty();
var isOk = hasKey && hasValue && hasNames;
if(!isOk){
// todo, check if necessary..
// throw new IllegalArgumentException("Missing orgenhetNavn for " + lederNavident);
}
}
}
}