-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Legg til hjelpefunksjoner for tidslinje fra familie-felles (#5073)
### 💰 Hva skal gjøres, og hvorfor? Favro: NAV-23270 Vi ønsker å ta i bruk tidslinjebiblioteket fra familie-felles i ba-sak. Starter migreringen med å importere biblioteket, og oversette hjelpefunksjonene fra det gamle tidlsinjebiblioteket til det nye. Kopierer og oversetter testene av de gamle funksjonene, for å sjekke at funksjonaliteten er lik. Sammenlikn gjerne nye og gamle funksjoner, for å sjekke at logikken er den samme.
- Loading branch information
1 parent
36fc15d
commit abfb509
Showing
28 changed files
with
1,656 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
55 changes: 55 additions & 0 deletions
55
...n/kotlin/no/nav/familie/ba/sak/kjerne/tidslinjefamiliefelles/komposisjon/TidslinjeJoin.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package no.nav.familie.ba.sak.kjerne.tidslinjefamiliefelles.komposisjon | ||
|
||
import no.nav.familie.tidslinje.Tidslinje | ||
import no.nav.familie.tidslinje.tomTidslinje | ||
import no.nav.familie.tidslinje.utvidelser.kombinerMed | ||
|
||
/** | ||
* Extension-metode for å kombinere to nøkkel-verdi-map'er der verdiene er tidslinjer | ||
* Nøkkelen må være av samme type K | ||
* Verdiene i tidslinjene i map'en på venstre side må alle være av typen V | ||
* Verdiene i tidslinjene i map'en på høyre side må alle være av typen H | ||
* Kombinator-funksjonen kalles med verdiene av fra venstre og høyre tidslinje for samme nøkkel og tidspunkt. | ||
* <null> blir sendt som verdier hvis venstre, høyre eller begge tidslinjer mangler verdi for et tidspunkt | ||
* Resultatet er en ny map der nøklene er av type K, og tidslinjene har innhold av typen (nullable) R. | ||
* Bare nøkler som finnes i begge map'ene vil finnes i den resulterende map'en | ||
*/ | ||
fun <K, V, H, R> Map<K, Tidslinje<V>>.join( | ||
høyreTidslinjer: Map<K, Tidslinje<H>>, | ||
kombinator: (V?, H?) -> R?, | ||
): Map<K, Tidslinje<R>> { | ||
val venstreTidslinjer = this | ||
val alleNøkler = venstreTidslinjer.keys.intersect(høyreTidslinjer.keys) | ||
|
||
return alleNøkler.associateWith { nøkkel -> | ||
val venstreTidslinje = venstreTidslinjer.getOrDefault(nøkkel, tomTidslinje()) | ||
val høyreTidslinje = høyreTidslinjer.getOrDefault(nøkkel, tomTidslinje()) | ||
|
||
venstreTidslinje.kombinerMed(høyreTidslinje, kombinator) | ||
} | ||
} | ||
|
||
/** | ||
* Extension-metode for å kombinere to nøkkel-verdi-map'er der verdiene er tidslinjer | ||
* Nøkkelen må være av samme type K | ||
* Verdiene i tidslinjene i map'en på venstre side må alle være av typen V | ||
* Verdiene i tidslinjene i map'en på høyre side må alle være av typen H | ||
* Kombinator-funksjonen kalles med verdiene av fra venstre og høyre tidslinje for samme nøkkel og tidspunkt. | ||
* Kombinator-funksjonen blir IKKE kalt hvis venstre, høyre eller begge tidslinjer mangler verdi for et tidspunkt | ||
* Resultatet er en ny map der nøklene er av type K, og tidslinjene har innhold av typen (nullable) R. | ||
* Bare nøkler som finnes i begge map'ene vil finnes i den resulterende map'en | ||
*/ | ||
fun <K, V, H, R> Map<K, Tidslinje<V>>.joinIkkeNull( | ||
høyreTidslinjer: Map<K, Tidslinje<H>>, | ||
kombinator: (V, H) -> R?, | ||
): Map<K, Tidslinje<R>> { | ||
val venstreTidslinjer = this | ||
val alleNøkler = venstreTidslinjer.keys.intersect(høyreTidslinjer.keys) | ||
|
||
return alleNøkler.associateWith { nøkkel -> | ||
val venstreTidslinje = venstreTidslinjer.getOrDefault(nøkkel, tomTidslinje()) | ||
val høyreTidslinje = høyreTidslinjer.getOrDefault(nøkkel, tomTidslinje()) | ||
|
||
venstreTidslinje.kombinerUtenNullMed(høyreTidslinje, kombinator) | ||
} | ||
} |
143 changes: 143 additions & 0 deletions
143
...in/no/nav/familie/ba/sak/kjerne/tidslinjefamiliefelles/komposisjon/TidslinjeKombinator.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
package no.nav.familie.ba.sak.kjerne.tidslinjefamiliefelles.komposisjon | ||
|
||
import no.nav.familie.tidslinje.Null | ||
import no.nav.familie.tidslinje.Tidslinje | ||
import no.nav.familie.tidslinje.Udefinert | ||
import no.nav.familie.tidslinje.Verdi | ||
import no.nav.familie.tidslinje.tilPeriodeVerdi | ||
import no.nav.familie.tidslinje.utvidelser.biFunksjon | ||
import no.nav.familie.tidslinje.utvidelser.kombinerMed | ||
import no.nav.familie.tidslinje.utvidelser.map | ||
import no.nav.familie.tidslinje.utvidelser.slåSammen | ||
import no.nav.familie.tidslinje.utvidelser.trim | ||
|
||
/** | ||
* Extension-metode for å kombinere to tidslinjer der begge har verdi | ||
* Kombinasjonen baserer seg på å iterere gjennom alle tidspunktene | ||
* Hver av tidslinjene kan ha ulik type, hhv V og H | ||
* Hvis V eller H mangler verdi, så vil ikke resulterende tidslinje få en verdi for det tidspunktet | ||
* Kombintor-funksjonen tar ellers V og H og returnerer (nullable) R | ||
* Hvis kombinator-funksjonen returner <null>, antas det at tidslinjen ikke skal ha verdi for tidspunktet | ||
* Resultatet er en tidslinje med verdi R | ||
*/ | ||
fun <V, H, R> Tidslinje<V>.kombinerUtenNullMed( | ||
høyreTidslinje: Tidslinje<H>, | ||
kombineringsfunksjon: (V, H) -> R?, | ||
): Tidslinje<R> = | ||
this.biFunksjon(høyreTidslinje) { periodeverdiVenstre, periodeverdiHøyre -> | ||
when { | ||
periodeverdiVenstre is Verdi && periodeverdiHøyre is Verdi -> | ||
kombineringsfunksjon(periodeverdiVenstre.verdi, periodeverdiHøyre.verdi).tilPeriodeVerdi() | ||
|
||
else -> Null() | ||
} | ||
} | ||
|
||
/** | ||
* Extension-metode for å kombinere liste av tidslinjer | ||
* Kombinasjonen baserer seg på å iterere gjennom alle tidspunktene fra alle tidslinjene | ||
* Verdi (V) må være av samme type | ||
* Kombintor-funksjonen tar inn Iterable<V> og returner (nullable) R | ||
* Null-verdier fjernes før de sendes til kombinator-funksjonen, som betyr at en tom iterator kan bli sendt | ||
* Hvis resultatet fra kombinatoren er null, tolkes det som at det ikke skal være en verdi | ||
* Resultatet er en tidslinje med verdi R | ||
*/ | ||
fun <V, R> Collection<Tidslinje<V>>.kombinerUtenNull( | ||
listeKombinator: (Iterable<V>) -> R?, | ||
): Tidslinje<R> = kombinerNullableKombinator { it.filterNotNull().let(listeKombinator) } | ||
|
||
/** | ||
* Extension-metode for å kombinere liste av tidslinjer | ||
* Kombinasjonen baserer seg på å iterere gjennom alle tidspunktene fra alle tidslinjene | ||
* Verdi (V) må være av samme type | ||
* Kombintor-funksjonen tar inn Iterable<V> og returner (nullable) R | ||
* Null-verdier fjernes, og listen av verdier sendes til kombinator-funksjonen bare hvis den inneholder verdier | ||
* Hvis reesultatet fra kombinatoren er null, tolkes det som at det ikke skal være en verdi | ||
* Resultatet er en tidslinje med verdi R | ||
*/ | ||
fun <V, R> Collection<Tidslinje<V>>.kombinerUtenNullOgIkkeTom( | ||
listeKombinator: (Iterable<V>) -> R?, | ||
): Tidslinje<R> = kombinerNullableKombinator { it.filterNotNull().takeIf { it.isNotEmpty() }?.let(listeKombinator) } | ||
|
||
/** | ||
* Extension-metode for å kombinere liste av tidslinjer | ||
* Kombinasjonen baserer seg på å iterere gjennom alle tidspunktene fra alle tidslinjene | ||
* Verdien V må være av samme type | ||
* Resultatet er en tidslinje med verdi Iterable<V> | ||
*/ | ||
fun <V> Collection<Tidslinje<V>>.kombiner() = this.kombinerNullableKombinator { if (it.toList().isNotEmpty()) it else null } | ||
|
||
/** | ||
* Extension-metode for å kombinere en nøkkel-verdi-map'er der verdiene er tidslinjer, med en enkelt tidslinje | ||
* Verdien i tidslinjene i map'en på venstre side må alle være av typen V | ||
* Verdien i tidslinjen på høyre side er av typen H | ||
* Kombinator-funksjonen kalles for hvert tidspunkt med med verdien for det tidspunktet fra høyre tidslinje og | ||
* verdien fra den enkelte av venstre tidslinjer etter tur. | ||
* Kombinator-funksjonen blir IKKE kalt hvis venstre, høyre eller begge tidslinjer mangler verdi for et tidspunkt | ||
* Resultatet er en ny map der nøklene er av type K, og tidslinjene har verdi av typen (nullable) R. | ||
*/ | ||
fun <K, V, H, R> Map<K, Tidslinje<V>>.kombinerKunVerdiMed( | ||
høyreTidslinje: Tidslinje<H>, | ||
kombinator: (V, H) -> R?, | ||
): Map<K, Tidslinje<R>> { | ||
val venstreTidslinjer = this | ||
|
||
return venstreTidslinjer.mapValues { (_, venstreTidslinje) -> | ||
venstreTidslinje.kombinerUtenNullMed(høyreTidslinje, kombinator) | ||
} | ||
} | ||
|
||
/** | ||
* Extension-metode for å kombinere tre tidslinjer | ||
* Kombinasjonen baserer seg på å iterere gjennom alle tidspunktene fra alle tidslinjene | ||
* Hver av tidslinjene kan ha ulik type, hhv A, B og C | ||
* Kombintor-funksjonen tar inn av A, B og C og returner (nullable) R | ||
* Resultatet er en tidslinje med verdi R | ||
*/ | ||
fun <A, B, C, R> Tidslinje<A>.kombinerKunVerdiMed( | ||
tidslinjeB: Tidslinje<B>, | ||
tidslinjeC: Tidslinje<C>, | ||
kombinator: (A, B, C) -> R?, | ||
): Tidslinje<R> = | ||
this.kombinerMed(tidslinjeB, tidslinjeC) { a, b, c -> | ||
when { | ||
a != null && b != null && c != null -> kombinator(a, b, c) | ||
else -> null | ||
} | ||
} | ||
|
||
fun <V> Tidslinje<V>.erIkkeTom() = !this.erTom() | ||
|
||
fun <V, H> Tidslinje<V>.harOverlappMed(tidslinje: Tidslinje<H>) = this.kombinerUtenNullMed(tidslinje) { v, h -> true }.trim(Null()).erIkkeTom() | ||
|
||
fun <V, H> Tidslinje<V>.harIkkeOverlappMed(tidslinje: Tidslinje<H>) = !this.harOverlappMed(tidslinje) | ||
|
||
fun <V, H> Tidslinje<V>.kombinerMedNullable( | ||
høyreTidslinje: Tidslinje<H>?, | ||
kombinator: (V?, H?) -> V?, | ||
): Tidslinje<V> = | ||
if (høyreTidslinje != null) { | ||
kombinerMed(høyreTidslinje, kombinator) | ||
} else { | ||
this | ||
} | ||
|
||
/** | ||
* Extension-metode for å kombinere liste av tidslinjer | ||
* Kombinasjonen baserer seg på å iterere gjennom alle tidspunktene fra alle tidslinjene | ||
* Verdi (V) må være av samme type | ||
* Kombintor-funksjonen tar inn Iterable<V> og returner (nullable) R | ||
* Resultatet er en tidslinje med verdi R | ||
*/ | ||
fun <V, R> Collection<Tidslinje<V>>.kombinerNullableKombinator(listeKombinator: (Iterable<V>) -> R?): Tidslinje<R> = | ||
this.slåSammen().map { | ||
when (it) { | ||
is Verdi -> { | ||
val resultat = listeKombinator(it.verdi) | ||
if (resultat != null) Verdi(resultat) else Null() | ||
} | ||
|
||
is Null -> Null() | ||
is Udefinert -> Udefinert() | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
...n/kotlin/no/nav/familie/ba/sak/kjerne/tidslinjefamiliefelles/komposisjon/TidslinjeUtil.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package no.nav.familie.ba.sak.kjerne.tidslinjefamiliefelles.komposisjon | ||
|
||
import no.nav.familie.ba.sak.common.førsteDagIInneværendeMåned | ||
import no.nav.familie.ba.sak.common.førsteDagINesteMåned | ||
import no.nav.familie.ba.sak.common.sisteDagIForrigeMåned | ||
import no.nav.familie.ba.sak.common.sisteDagIInneværendeMåned | ||
import no.nav.familie.ba.sak.common.sisteDagIMåned | ||
import no.nav.familie.ba.sak.kjerne.grunnlag.personopplysninger.Person | ||
import no.nav.familie.tidslinje.Periode | ||
import no.nav.familie.tidslinje.Tidslinje | ||
import no.nav.familie.tidslinje.tilTidslinje | ||
import java.time.LocalDate | ||
import java.time.YearMonth | ||
|
||
fun erUnder18ÅrVilkårTidslinje(fødselsdato: LocalDate): Tidslinje<Boolean> = | ||
opprettBooleanTidslinje( | ||
fraDato = fødselsdato.førsteDagINesteMåned(), | ||
tilDato = fødselsdato.plusYears(18).sisteDagIForrigeMåned(), | ||
) | ||
|
||
fun erUnder6ÅrTidslinje(person: Person): Tidslinje<Boolean> = | ||
opprettBooleanTidslinje( | ||
fraDato = person.fødselsdato.førsteDagIInneværendeMåned(), | ||
tilDato = person.fødselsdato.plusYears(6).sisteDagIForrigeMåned(), | ||
) | ||
|
||
fun erTilogMed3ÅrTidslinje(fødselsdato: LocalDate): Tidslinje<Boolean> = | ||
opprettBooleanTidslinje( | ||
fraDato = fødselsdato.førsteDagINesteMåned(), | ||
tilDato = fødselsdato.plusYears(3).sisteDagIMåned(), | ||
) | ||
|
||
fun opprettBooleanTidslinje( | ||
fraÅrMåned: YearMonth, | ||
tilÅrMåned: YearMonth, | ||
) = listOf( | ||
Periode( | ||
verdi = true, | ||
fom = fraÅrMåned.førsteDagIInneværendeMåned(), | ||
tom = tilÅrMåned.sisteDagIInneværendeMåned(), | ||
), | ||
).tilTidslinje() | ||
|
||
fun opprettBooleanTidslinje( | ||
fraDato: LocalDate, | ||
tilDato: LocalDate, | ||
) = listOf(Periode(verdi = true, fom = fraDato, tom = tilDato)).tilTidslinje() |
22 changes: 22 additions & 0 deletions
22
...lin/no/nav/familie/ba/sak/kjerne/tidslinjefamiliefelles/matematikk/BigDecimalTidslinje.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package no.nav.familie.ba.sak.kjerne.tidslinjefamiliefelles.matematikk | ||
|
||
import no.nav.familie.ba.sak.kjerne.personident.Aktør | ||
import no.nav.familie.ba.sak.kjerne.tidslinjefamiliefelles.komposisjon.join | ||
import no.nav.familie.ba.sak.kjerne.tidslinjefamiliefelles.komposisjon.kombinerUtenNullOgIkkeTom | ||
import no.nav.familie.ba.sak.kjerne.tidslinjefamiliefelles.transformasjon.mapIkkeNull | ||
import no.nav.familie.tidslinje.Tidslinje | ||
import java.math.BigDecimal | ||
import java.math.RoundingMode | ||
|
||
fun <K> Map<K, Tidslinje<BigDecimal>>.minus( | ||
bTidslinjer: Map<K, Tidslinje<BigDecimal>>, | ||
) = this.join(bTidslinjer) { a, b -> | ||
when { | ||
a != null && b != null -> a - b | ||
else -> a | ||
} | ||
} | ||
|
||
fun Map<Aktør, Tidslinje<BigDecimal>>.sum() = values.kombinerUtenNullOgIkkeTom { it.reduce { sum, verdi -> sum.plus(verdi) } } | ||
|
||
fun Tidslinje<BigDecimal>.rundAvTilHeltall() = this.mapIkkeNull { it.setScale(0, RoundingMode.HALF_UP) } |
9 changes: 9 additions & 0 deletions
9
.../no/nav/familie/ba/sak/kjerne/tidslinjefamiliefelles/matematikk/SammenliknbarTidslinje.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package no.nav.familie.ba.sak.kjerne.tidslinjefamiliefelles.matematikk | ||
|
||
import no.nav.familie.ba.sak.kjerne.tidslinjefamiliefelles.komposisjon.joinIkkeNull | ||
import no.nav.familie.tidslinje.Tidslinje | ||
|
||
fun <K, V : Comparable<V>> minsteAvHver( | ||
aTidslinjer: Map<K, Tidslinje<V>>, | ||
bTidslinjer: Map<K, Tidslinje<V>>, | ||
) = aTidslinjer.joinIkkeNull(bTidslinjer) { a, b -> minOf(a, b) } |
84 changes: 84 additions & 0 deletions
84
...n/no/nav/familie/ba/sak/kjerne/tidslinjefamiliefelles/transformasjon/BeskjæreTidslinje.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package no.nav.familie.ba.sak.kjerne.tidslinjefamiliefelles.transformasjon | ||
|
||
import no.nav.familie.tidslinje.Tidslinje | ||
import no.nav.familie.tidslinje.tomTidslinje | ||
import no.nav.familie.tidslinje.utvidelser.klipp | ||
import java.time.LocalDate | ||
|
||
/** | ||
* Extension-metode for å beskjære (forkorte) en tidslinje etter til-og-med fra en annen tidslinje | ||
* Etter beskjæringen vil tidslinjen maksimalt strekke seg fra [this]s startTidspunkt og til [tidslinje]s sluttTidspunkt | ||
* Perioder som ligger helt utenfor grensene vil forsvinne. | ||
* Perioden i hver ende som ligger delvis innenfor, vil forkortes. | ||
* Hvis ny og eksisterende grenseverdi begge er uendelige, vil den nye benyttes | ||
* Beskjæring mot tom tidslinje vil gi tom tidslinje | ||
*/ | ||
fun <I> Tidslinje<I>.beskjærTilOgMedEtter(tidslinje: Tidslinje<*>): Tidslinje<I> = | ||
when { | ||
tidslinje.erTom() -> tomTidslinje() | ||
else -> | ||
klipp( | ||
startsTidspunkt = startsTidspunkt, | ||
sluttTidspunkt = tidslinje.kalkulerSluttTidspunkt(), | ||
) | ||
} | ||
|
||
/** | ||
* Extension-metode for å beskjære (forkorte) en tidslinje | ||
* Etter beskjæringen vil tidslinjen maksimalt strekke seg fra innsendt [fraOgMed] og til [tilOgMed] | ||
* Perioder som ligger helt utenfor grensene vil forsvinne. | ||
* Perioden i hver ende som ligger delvis innenfor, vil forkortes. | ||
* Uendelige endepunkter vil beskjæres til endelig | ||
*/ | ||
fun <V> Tidslinje<V>.beskjær( | ||
fraOgMed: LocalDate, | ||
tilOgMed: LocalDate, | ||
): Tidslinje<V> = | ||
when { | ||
erTom() -> tomTidslinje() | ||
else -> | ||
klipp( | ||
startsTidspunkt = fraOgMed, | ||
sluttTidspunkt = tilOgMed, | ||
) | ||
} | ||
|
||
/** | ||
* Extension-metode for å beskjære fom dato på en tidslinje | ||
* Etter beskjæringen vil tidslinjen maksimalt strekke seg fra innsendt [fraOgMed] og til eksisterende tilOgMed | ||
*/ | ||
fun <V> Tidslinje<V>.beskjærFraOgMed( | ||
fraOgMed: LocalDate, | ||
): Tidslinje<V> = | ||
when { | ||
erTom() -> tomTidslinje() | ||
else -> | ||
klipp( | ||
startsTidspunkt = fraOgMed, | ||
sluttTidspunkt = kalkulerSluttTidspunkt(), | ||
) | ||
} | ||
|
||
/** | ||
* Extension-metode for å beskjære tom dato på en tidslinje | ||
* Etter beskjæringen vil tidslinjen maksimalt strekke seg fra eksisterende fraOgMed og til innsendt [tilOgMed] | ||
*/ | ||
fun <V> Tidslinje<V>.beskjærTilOgMed( | ||
tilOgMed: LocalDate, | ||
): Tidslinje<V> = | ||
when { | ||
erTom() -> tomTidslinje() | ||
else -> | ||
klipp( | ||
startsTidspunkt = startsTidspunkt, | ||
sluttTidspunkt = tilOgMed, | ||
) | ||
} | ||
|
||
/** | ||
* Extension-metode for å beskjære tom dato på et map av tidslinjer | ||
* Etter beskjæringen vil tidslinjen maksimalt strekke seg fra eksisterende fraOgMed og til innsendt [tilOgMed] | ||
*/ | ||
fun <K, V> Map<K, Tidslinje<V>>.beskjærTilOgMed( | ||
tilOgMed: LocalDate, | ||
): Map<K, Tidslinje<V>> = this.mapValues { (_, tidslinje) -> tidslinje.beskjærTilOgMed(tilOgMed) } |
Oops, something went wrong.