-
Notifications
You must be signed in to change notification settings - Fork 129
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7165 from deutschebank/db-contrib/waltz-7146-ripp…
…le-assessments Db contrib/waltz 7146 ripple assessments
- Loading branch information
Showing
16 changed files
with
1,059 additions
and
16 deletions.
There are no files selected for viewing
466 changes: 466 additions & 0 deletions
466
waltz-data/src/main/java/org/finos/waltz/data/assessment_rating/AssessmentRatingRippler.java
Large diffs are not rendered by default.
Oops, something went wrong.
27 changes: 27 additions & 0 deletions
27
...ata/src/test/java/org/finos/waltz/data/assessment_rating/AssessmentRatingRipplerTest.java
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,27 @@ | ||
package org.finos.waltz.data.assessment_rating; | ||
|
||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
import org.finos.waltz.model.assessment_definition.AssessmentRipplerJobConfiguration; | ||
import org.finos.waltz.model.assessment_definition.AssessmentRipplerJobStep; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import static org.finos.waltz.common.CollectionUtilities.first; | ||
import static org.junit.jupiter.api.Assertions.*; | ||
|
||
class AssessmentRatingRipplerTest { | ||
|
||
|
||
@Test | ||
public void testSettingsParse() throws JsonProcessingException { | ||
String value = "[ { \"from\" : \"FROM_DEF\", \"to\" : \"TO_DEF\" } ]"; | ||
AssessmentRipplerJobConfiguration config = AssessmentRatingRippler.parseConfig("demoRippler", value); | ||
|
||
assertEquals("demoRippler", config.name()); | ||
assertEquals(1, config.steps().size()); | ||
|
||
AssessmentRipplerJobStep step = first(config.steps()); | ||
assertEquals("FROM_DEF", step.fromDef()); | ||
assertEquals("TO_DEF", step.toDef()); | ||
} | ||
|
||
} |
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
183 changes: 183 additions & 0 deletions
183
...t/src/test/java/org/finos/waltz/integration_test/inmem/service/AssessmentRipplerTest.java
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,183 @@ | ||
package org.finos.waltz.integration_test.inmem.service; | ||
|
||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
import org.finos.waltz.data.assessment_rating.AssessmentRatingRippler; | ||
import org.finos.waltz.data.settings.SettingsDao; | ||
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.assessment_definition.AssessmentRipplerJobStep; | ||
import org.finos.waltz.model.assessment_definition.AssessmentVisibility; | ||
import org.finos.waltz.model.assessment_definition.ImmutableAssessmentRipplerJobStep; | ||
import org.finos.waltz.model.settings.ImmutableSetting; | ||
import org.finos.waltz.model.settings.Setting; | ||
import org.finos.waltz.schema.tables.AssessmentRating; | ||
import org.finos.waltz.test_common.helpers.AppHelper; | ||
import org.finos.waltz.test_common.helpers.AssessmentHelper; | ||
import org.finos.waltz.test_common.helpers.MeasurableHelper; | ||
import org.finos.waltz.test_common.helpers.RatingSchemeHelper; | ||
import org.junit.jupiter.api.Test; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
|
||
import static org.finos.waltz.common.JacksonUtilities.getJsonMapper; | ||
import static org.finos.waltz.common.ListUtilities.asList; | ||
import static org.finos.waltz.model.EntityReference.mkRef; | ||
import static org.finos.waltz.schema.Tables.ASSESSMENT_RATING; | ||
import static org.finos.waltz.test_common.helpers.NameHelper.mkName; | ||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.assertNull; | ||
import static org.junit.jupiter.api.Assertions.assertThrows; | ||
|
||
public class AssessmentRipplerTest extends BaseInMemoryIntegrationTest { | ||
|
||
private static final AssessmentRating ar = ASSESSMENT_RATING; | ||
|
||
@Autowired | ||
private AppHelper appHelper; | ||
|
||
@Autowired | ||
private MeasurableHelper measurableHelper; | ||
|
||
@Autowired | ||
private AssessmentHelper assessmentHelper; | ||
|
||
@Autowired | ||
private RatingSchemeHelper ratingSchemeHelper; | ||
|
||
@Autowired | ||
private SettingsDao settingsDao; | ||
|
||
@Autowired | ||
private AssessmentRatingRippler assessmentRatingRippler; | ||
|
||
private final String stem = "ripple"; | ||
|
||
|
||
@Test | ||
public void cannotRippleBetweenAssessmentsWithDifferingRatingSchemes() { | ||
long schemeA = ratingSchemeHelper.createEmptyRatingScheme(mkName(stem, "bad_ripple_a")); | ||
long schemeB = ratingSchemeHelper.createEmptyRatingScheme(mkName(stem, "bad_ripple_b")); | ||
|
||
long assmtA = assessmentHelper.createDefinition(schemeA, mkName(stem, "ripple assmt A"), null, AssessmentVisibility.SECONDARY, stem); | ||
long assmtB = assessmentHelper.createDefinition(schemeB, mkName(stem, "ripple assmt B"), null, AssessmentVisibility.SECONDARY, stem); | ||
String assmtA_extId = mkName(stem, "ASSMT_A"); | ||
String assmtB_extId = mkName(stem, "ASSMT_B"); | ||
assessmentHelper.setDefExtId(assmtA, assmtA_extId); | ||
assessmentHelper.setDefExtId(assmtB, assmtB_extId); | ||
|
||
assertThrows( | ||
IllegalArgumentException.class, | ||
() -> AssessmentRatingRippler.rippleAssessment( | ||
getDsl(), | ||
"admin", | ||
"rippler_test", | ||
assmtA_extId, | ||
assmtB_extId)); | ||
} | ||
|
||
|
||
@Test | ||
public void canRippleBetweenAssessmentsWithSameRatingSchemes() throws JsonProcessingException { | ||
// setup app, measurable, and rating | ||
EntityReference appRef = appHelper.createNewApp(mkName(stem, "ripple_app"), ouIds.root); | ||
long categoryId = measurableHelper.createMeasurableCategory(mkName(stem, "ripple_mc")); | ||
long measurableId = measurableHelper.createMeasurable(mkName(stem, "ripple_m"), categoryId); | ||
|
||
// link app to measurable | ||
measurableHelper.createRating(appRef, measurableId); | ||
|
||
// create schemes, rating items and assessments | ||
long scheme = ratingSchemeHelper.createEmptyRatingScheme(mkName(stem, "good_ripple_scheme")); | ||
Long rsiId = ratingSchemeHelper.saveRatingItem(scheme, mkName(stem, "ripple_rsi"), 0, "pink", "P"); | ||
long assmtA = assessmentHelper.createDefinition(scheme, mkName(stem, "ripple assmt A"), null, AssessmentVisibility.SECONDARY, stem, EntityKind.MEASURABLE, mkRef(EntityKind.MEASURABLE_CATEGORY, categoryId)); | ||
long assmtB = assessmentHelper.createDefinition(scheme, mkName(stem, "ripple assmt B"), null, AssessmentVisibility.SECONDARY, stem, EntityKind.APPLICATION, null); | ||
String assmtA_extId = mkName(stem, "ASSMT_A"); | ||
String assmtB_extId = mkName(stem, "ASSMT_B"); | ||
assessmentHelper.setDefExtId(assmtA, assmtA_extId); | ||
assessmentHelper.setDefExtId(assmtB, assmtB_extId); | ||
|
||
// link assessment rating to measurable | ||
assessmentHelper.createAssessment(assmtA, mkRef(EntityKind.MEASURABLE, measurableId), rsiId); | ||
|
||
AssessmentRipplerJobStep rippleStep = ImmutableAssessmentRipplerJobStep | ||
.builder() | ||
.fromDef(assmtA_extId) | ||
.toDef(assmtB_extId) | ||
.build(); | ||
Setting rippleSetting = ImmutableSetting | ||
.builder() | ||
.name("job.RIPPLE_ASSESSMENTS."+mkName(stem, "rippleConfig")) | ||
.value(getJsonMapper().writeValueAsString(asList(rippleStep))) | ||
.build(); | ||
settingsDao.create(rippleSetting); | ||
|
||
// ripple | ||
assessmentRatingRippler.rippleAssessments(); | ||
|
||
// verify | ||
assertEquals( | ||
rsiId, | ||
fetchAssessmentRatingItemId(appRef, assmtB), | ||
"Rating will have rippled from measurable to application"); | ||
} | ||
|
||
|
||
@Test | ||
public void canRippleUsingTheSettingsTableDefinitions() { | ||
// setup app, measurable, and rating | ||
EntityReference appRef = appHelper.createNewApp(mkName(stem, "ripple_app"), ouIds.root); | ||
EntityReference unrelatedRef = appHelper.createNewApp(mkName(stem, "ripple_unrelated_app"), ouIds.root); | ||
long categoryId = measurableHelper.createMeasurableCategory(mkName(stem, "ripple_mc")); | ||
long measurableId = measurableHelper.createMeasurable(mkName(stem, "ripple_m"), categoryId); | ||
|
||
// link app to measurable | ||
measurableHelper.createRating(appRef, measurableId); | ||
|
||
// create schemes, rating items and assessments | ||
long scheme = ratingSchemeHelper.createEmptyRatingScheme(mkName(stem, "good_ripple_scheme")); | ||
Long rsiId = ratingSchemeHelper.saveRatingItem(scheme, mkName(stem, "ripple_rsi"), 0, "pink", "P"); | ||
long assmtA = assessmentHelper.createDefinition(scheme, mkName(stem, "ripple assmt A"), null, AssessmentVisibility.SECONDARY, stem, EntityKind.MEASURABLE, mkRef(EntityKind.MEASURABLE_CATEGORY, categoryId)); | ||
long assmtB = assessmentHelper.createDefinition(scheme, mkName(stem, "ripple assmt B"), null, AssessmentVisibility.SECONDARY, stem, EntityKind.APPLICATION, null); | ||
String assmtA_extId = mkName(stem, "ASSMT_A"); | ||
String assmtB_extId = mkName(stem, "ASSMT_B"); | ||
assessmentHelper.setDefExtId(assmtA, assmtA_extId); | ||
assessmentHelper.setDefExtId(assmtB, assmtB_extId); | ||
|
||
// link assessment rating to measurable | ||
assessmentHelper.createAssessment(assmtA, mkRef(EntityKind.MEASURABLE, measurableId), rsiId); | ||
|
||
// ripple | ||
AssessmentRatingRippler.rippleAssessment( | ||
getDsl(), | ||
"admin", | ||
"rippler_test", | ||
assmtA_extId, | ||
assmtB_extId); | ||
|
||
// verify | ||
assertEquals( | ||
rsiId, | ||
fetchAssessmentRatingItemId(appRef, assmtB), | ||
"Rating will have rippled from measurable to application"); | ||
|
||
assertNull( | ||
fetchAssessmentRatingItemId(unrelatedRef, assmtB), | ||
"Rating won't have rippled to an unrelated app"); | ||
} | ||
|
||
|
||
// --- helpers ------------- | ||
|
||
private Long fetchAssessmentRatingItemId(EntityReference ref, | ||
long assessmentDefinitionId) { | ||
return getDsl() | ||
.select(ar.RATING_ID) | ||
.from(ar) | ||
.where(ar.ENTITY_KIND.eq(ref.kind().name())) | ||
.and(ar.ENTITY_ID.eq(ref.id())) | ||
.and(ar.ASSESSMENT_DEFINITION_ID.eq(assessmentDefinitionId)) | ||
.fetchOne(ar.RATING_ID); | ||
} | ||
|
||
|
||
} |
71 changes: 71 additions & 0 deletions
71
waltz-model/src/main/java/org/finos/waltz/model/PairDiffResult.java
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,71 @@ | ||
package org.finos.waltz.model; | ||
|
||
import org.immutables.value.Value; | ||
import org.jooq.lambda.tuple.Tuple2; | ||
|
||
import java.util.Collection; | ||
import java.util.Map; | ||
import java.util.Set; | ||
import java.util.function.BiPredicate; | ||
import java.util.function.Function; | ||
import java.util.stream.Collectors; | ||
|
||
import static org.finos.waltz.common.MapUtilities.indexBy; | ||
import static org.jooq.lambda.tuple.Tuple.tuple; | ||
|
||
@Value.Immutable | ||
public abstract class PairDiffResult<A, B> { | ||
|
||
public abstract Collection<Tuple2<A, B>> allIntersection(); | ||
public abstract Collection<B> otherOnly(); | ||
public abstract Collection<A> waltzOnly(); | ||
public abstract Collection<Tuple2<A, B>> differingIntersection(); | ||
|
||
|
||
public static <A, B, K> PairDiffResult<A, B> mkPairDiff(Collection<A> waltzRecords, | ||
Collection<B> otherRecords, | ||
Function<A, K> aKeyFn, | ||
Function<B, K> bKeyFn, | ||
BiPredicate<A, B> equalityPredicate) { | ||
Map<K, A> waltzByKey = indexBy(waltzRecords, aKeyFn); | ||
Map<K, B> othersByKey = indexBy(otherRecords, bKeyFn); | ||
|
||
Set<B> otherOnly = otherRecords.stream() | ||
.filter(f -> !waltzByKey.containsKey(bKeyFn.apply(f))) | ||
.collect(Collectors.toSet()); | ||
|
||
Set<A> waltzOnly = waltzRecords.stream() | ||
.filter(f -> !othersByKey.containsKey(aKeyFn.apply(f))) | ||
.collect(Collectors.toSet()); | ||
|
||
Set<Tuple2<A, B>> intersect = otherRecords.stream() | ||
.map(other -> tuple( | ||
waltzByKey.get(bKeyFn.apply(other)), | ||
other)) | ||
.filter(t -> t.v1 != null) | ||
.collect(Collectors.toSet()); | ||
|
||
Set<Tuple2<A, B>> differingIntersection = intersect.stream() | ||
.filter(t -> ! equalityPredicate.test(t.v1, t.v2)) | ||
.collect(Collectors.toSet()); | ||
|
||
return ImmutablePairDiffResult | ||
.<A, B>builder() | ||
.otherOnly(otherOnly) | ||
.waltzOnly(waltzOnly) | ||
.allIntersection(intersect) | ||
.differingIntersection(differingIntersection) | ||
.build(); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return String.format( | ||
"%s - [Intersection: %s records, Other: %s records, Waltz: %s records, Differing Intersection: %s records]", | ||
getClass().getName(), | ||
allIntersection().size(), | ||
otherOnly().size(), | ||
waltzOnly().size(), | ||
differingIntersection().size()); | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
...n/java/org/finos/waltz/model/assessment_definition/AssessmentRipplerJobConfiguration.java
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,18 @@ | ||
package org.finos.waltz.model.assessment_definition; | ||
|
||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; | ||
import com.fasterxml.jackson.databind.annotation.JsonSerialize; | ||
import org.immutables.value.Value; | ||
|
||
import java.util.List; | ||
|
||
@Value.Immutable | ||
@JsonDeserialize(as = ImmutableAssessmentRipplerJobConfiguration.class) | ||
@JsonSerialize(as = ImmutableAssessmentRipplerJobConfiguration.class) | ||
public interface AssessmentRipplerJobConfiguration { | ||
|
||
String name(); | ||
|
||
List<AssessmentRipplerJobStep> steps(); | ||
|
||
} |
19 changes: 19 additions & 0 deletions
19
...l/src/main/java/org/finos/waltz/model/assessment_definition/AssessmentRipplerJobStep.java
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,19 @@ | ||
package org.finos.waltz.model.assessment_definition; | ||
|
||
import com.fasterxml.jackson.annotation.JsonAlias; | ||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; | ||
import com.fasterxml.jackson.databind.annotation.JsonSerialize; | ||
import org.immutables.value.Value; | ||
|
||
@Value.Immutable | ||
@JsonDeserialize(as = ImmutableAssessmentRipplerJobStep.class) | ||
@JsonSerialize(as = ImmutableAssessmentRipplerJobStep.class) | ||
public interface AssessmentRipplerJobStep { | ||
|
||
@JsonAlias({"from", "from_def"}) | ||
String fromDef(); | ||
|
||
@JsonAlias({"to", "to_def"}) | ||
String toDef(); | ||
|
||
} |
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
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
Oops, something went wrong.