ResourceUnitsResponse.java
package no.nav.data.team.resource.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.Singular;
import lombok.extern.slf4j.Slf4j;
import no.nav.data.common.utils.DateUtil;
import no.nav.data.team.resource.NomClient;
import no.nav.data.team.resource.domain.Resource;
import no.nav.nom.graphql.model.*;
import no.nav.nom.graphql.model.OrgEnhetDto;
import no.nav.nom.graphql.model.OrgEnhetsLederDto;
import no.nav.nom.graphql.model.RessursOrgTilknytningDto;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import static no.nav.data.common.utils.StreamUtils.convert;
import static no.nav.data.common.utils.StreamUtils.distinctByKey;
import static no.nav.data.common.utils.StreamUtils.safeStream;
@Slf4j
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ResourceUnitsResponse {
private static final String TOP_LEVEL_AGRESSO_ID = "NAV";
private static final String IT_AVD_AGRESSO_ID = "854";
@Singular
List<Unit> units;
@Singular
List<ResourceResponse> members;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class Unit {
String agressoId;
String nomid;
String name;
String niva;
@JsonInclude(Include.NON_EMPTY)
ResourceResponse leader;
@JsonInclude(Include.NON_EMPTY)
Unit parentUnit;
}
public static ResourceUnitsResponse from(RessursDto nomRessurs, List<String> memberIdents, Function<String, Optional<OrgEnhetDto>> hentOrgEnhet) {
var units = new ArrayList<Unit>();
nomRessurs.getOrgTilknytning()
.stream()
.filter(dto -> DateUtil.isNow(dto.getGyldigFom(), dto.getGyldigTom()))
.map(RessursOrgTilknytningDto::getOrgEnhet)
.filter(distinctByKey(OrgEnhetDto::getId))
.forEach(org -> {
var unitBuilder = Unit.builder()
.nomid(org.getId())
.agressoId(org.getAgressoId())
.name(org.getNavn())
.niva(org.getOrgNiv());
findParentUnit(org.getId(), hentOrgEnhet)
.ifPresent(parentUnit ->
unitBuilder.parentUnit(Unit.builder()
.nomid(parentUnit.nomId())
.agressoId(parentUnit.agressoId())
.name(parentUnit.navn())
.niva(parentUnit.niva()).build()));
org.getLeder().stream().findFirst()
.map(OrgEnhetsLederDto::getRessurs)
.map(RessursDto::getNavident)
.filter(id -> !id.equals(nomRessurs.getNavident()))
.or(() -> nomRessurs.getLedere().stream()
.map(RessursLederDto::getRessurs)
.map(RessursDto::getNavident)
.findFirst()
)
.ifPresent(ident -> unitBuilder.leader(NomClient.getInstance()
.getByNavIdent(ident)
.map(Resource::convertToResponse)
.orElse(null))
);
units.add(unitBuilder.build());
});
var members = convert(memberIdents, ident -> NomClient.getInstance().getByNavIdent(ident).map(Resource::convertToResponse).orElse(null));
return new ResourceUnitsResponse(units, members);
}
private static Optional<UnitId> findParentUnit(String nomId, Function<String, Optional<OrgEnhetDto>> hentOrgEnhet) {
var org = hentOrgEnhet.apply(nomId).orElseThrow();
var trace = new ArrayList<OrgEnhetDto>();
trace.add(org);
var parent = firstValid(org.getOrganiseringer(), hentOrgEnhet);
while (parent != null && !parent.getId().equals(trace.get(0).getId()) && !TOP_LEVEL_AGRESSO_ID.equals(trace.get(0).getAgressoId())) {
trace.addFirst(parent);
parent = firstValid(parent.getOrganiseringer(), hentOrgEnhet);
}
if (trace.get(0).getAgressoId().equals(TOP_LEVEL_AGRESSO_ID)) {
return Optional.of(switch (trace.size()) {
case 1 -> new UnitId(trace.get(0));
case 2 -> new UnitId(trace.get(1));
default -> {
var itAvd = trace.stream().filter(o -> o.getAgressoId().equals(IT_AVD_AGRESSO_ID)).findFirst();
if (itAvd.isPresent()) {
// IT should be level=2, and IT-sub level=3, but we can be safe
var itAvdIdx = trace.indexOf(itAvd.get());
int itAvdSubIdx = itAvdIdx + 1;
if (itAvdSubIdx < trace.size()) {
yield new UnitId(trace.get(itAvdSubIdx).getAgressoId(), trace.get(itAvdIdx).getNavn() + " - " + trace.get(itAvdSubIdx).getNavn(), trace.get(itAvdSubIdx).getOrgNiv(), trace.get(itAvdSubIdx).getId());
}
}
yield new UnitId(trace.get(2));
}
});
}
return Optional.empty();
}
private static OrgEnhetDto firstValid(List<OrganiseringDto> organiseringer, Function<String, Optional<OrgEnhetDto>> hentOrgEnhet) {
return safeStream(organiseringer)
.filter(o -> o.getRetning() == RetningDto.over)
.filter(dto -> DateUtil.isNow(dto.getGyldigFom(), dto.getGyldigTom()))
.findFirst()
.map(OrganiseringDto::getOrgEnhet)
.map(OrgEnhetDto::getId)
.flatMap(hentOrgEnhet)
.orElse(null);
}
private record UnitId(String agressoId, String navn, String niva, String nomId) {
private UnitId(OrgEnhetDto org) {
this(org.getAgressoId(), org.getNavn(), org.getOrgNiv(), org.getId());
}
}
}