protected void registerConstraintMatch(RuleContext kcontext, final Runnable constraintUndoListener, Supplier<Score_> scoreSupplier) { AgendaItem<?> agendaItem = (AgendaItem) kcontext.getMatch(); ConstraintActivationUnMatchListener constraintActivationUnMatchListener = new ConstraintActivationUnMatchListener(constraintUndoListener); agendaItem.setCallback(constraintActivationUnMatchListener); if (constraintMatchEnabled) { List<Object> justificationList = extractJustificationList(kcontext); // Not needed in fast code: Add ConstraintMatch constraintActivationUnMatchListener.constraintMatchTotal = findConstraintMatchTotal(kcontext); ConstraintMatch constraintMatch = constraintActivationUnMatchListener.constraintMatchTotal .addConstraintMatch(justificationList, scoreSupplier.get()); List<Indictment> indictmentList = justificationList.stream() .distinct() // One match might have the same justification twice .map(justification -> { Indictment indictment = indictmentMap.computeIfAbsent(justification, k -> new Indictment(justification, zeroScore)); indictment.addConstraintMatch(constraintMatch); return indictment; }).collect(Collectors.toList()); constraintActivationUnMatchListener.constraintMatch = constraintMatch; constraintActivationUnMatchListener.indictmentList = indictmentList; } }
@Override public Map<Object, Indictment> getIndictmentMap() { if (!isConstraintMatchEnabled()) { throw new IllegalStateException("When constraintMatchEnabled (" + isConstraintMatchEnabled() + ") is disabled in the constructor, this method should not be called."); } Map<Object, Indictment> incrementalIndictmentMap = ((ConstraintMatchAwareIncrementalScoreCalculator<Solution_>) incrementalScoreCalculator) .getIndictmentMap(); if (incrementalIndictmentMap != null) { return incrementalIndictmentMap; } Map<Object, Indictment> indictmentMap = new LinkedHashMap<>(); // TODO use entitySize Score zeroScore = getScoreDefinition().getZeroScore(); for (ConstraintMatchTotal constraintMatchTotal : getConstraintMatchTotals()) { for (ConstraintMatch constraintMatch : constraintMatchTotal.getConstraintMatchSet()) { constraintMatch.getJustificationList().stream() .distinct() // One match might have the same justification twice .forEach(justification -> { Indictment indictment = indictmentMap.computeIfAbsent(justification, k -> new Indictment(justification, zeroScore)); indictment.addConstraintMatch(constraintMatch); }); } } return indictmentMap; }
@Test public void getScoreTotal() { TestdataEntity e1 = new TestdataEntity("e1"); TestdataEntity e2 = new TestdataEntity("e2"); TestdataEntity e3 = new TestdataEntity("e3"); Indictment indictment = new Indictment(e1, SimpleScore.ZERO); assertEquals(SimpleScore.ZERO, indictment.getScore()); ConstraintMatch match1 = new ConstraintMatch("package1", "constraint1", asList(e1), SimpleScore.of(-1)); indictment.addConstraintMatch(match1); assertEquals(SimpleScore.of(-1), indictment.getScore()); // Different constraintName ConstraintMatch match2 = new ConstraintMatch("package1", "constraint2", asList(e1), SimpleScore.of(-20)); indictment.addConstraintMatch(match2); assertEquals(SimpleScore.of(-21), indictment.getScore()); indictment.addConstraintMatch(new ConstraintMatch("package1", "constraint3", asList(e1, e2), SimpleScore.of(-300))); assertEquals(SimpleScore.of(-321), indictment.getScore()); // Different justification indictment.addConstraintMatch(new ConstraintMatch("package1", "constraint3", asList(e1, e3), SimpleScore.of(-4000))); assertEquals(SimpleScore.of(-4321), indictment.getScore()); // Almost duplicate, but e2 and e1 are in reverse order, so different justification indictment.addConstraintMatch(new ConstraintMatch("package1", "constraint3", asList(e2, e1), SimpleScore.of(-50000))); assertEquals(SimpleScore.of(-54321), indictment.getScore()); indictment.removeConstraintMatch(match2); assertEquals(SimpleScore.of(-54301), indictment.getScore()); indictment.removeConstraintMatch(match1); assertEquals(SimpleScore.of(-54300), indictment.getScore()); }