Skip to content

Commit

Permalink
MCR-3050 add "xor" support
Browse files Browse the repository at this point in the history
* fixes bug in order of child conditions
* add JUnit tests
  • Loading branch information
yagee-de committed Feb 23, 2024
1 parent ffba94a commit 07a0c54
Show file tree
Hide file tree
Showing 11 changed files with 284 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@
*/
package org.mycore.access.facts.condition.combined;

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;

import org.jdom2.Element;
import org.mycore.access.facts.MCRFactsAccessSystemHelper;
import org.mycore.access.facts.MCRFactsHolder;
import org.mycore.access.facts.condition.MCRAbstractCondition;
import org.mycore.access.facts.model.MCRCombinedCondition;
import org.mycore.access.facts.model.MCRCondition;
Expand All @@ -33,9 +35,10 @@
* @author Robert Stephan
*
*/
public abstract class MCRAbstractCombinedCondition extends MCRAbstractCondition implements MCRCombinedCondition {
sealed public abstract class MCRAbstractCombinedCondition extends MCRAbstractCondition implements MCRCombinedCondition
permits MCRAndCondition, MCRNotCondition, MCROrCondition, MCRXorCondition {

protected Set<MCRCondition> conditions = new HashSet<>();
protected Set<MCRCondition> conditions = new LinkedHashSet<>();

public void add(MCRCondition condition) {
conditions.add(condition);
Expand All @@ -55,6 +58,7 @@ public Set<MCRCondition> getChildConditions() {
return conditions;
}

@Deprecated
public void debugInfoForMatchingChildElement(MCRCondition c, boolean matches) {
if (isDebug()) {
Element el = c.getBoundElement();
Expand All @@ -64,4 +68,14 @@ public void debugInfoForMatchingChildElement(MCRCondition c, boolean matches) {
}
}

boolean addDebugInfoIfRequested(MCRCondition c, MCRFactsHolder facts) {
if (!isDebug()) {
return c.matches(facts);
}
boolean matches = c.matches(facts);
Objects.requireNonNull(c.getBoundElement(), "Condition is not bound to an element.")
.setAttribute("_matches", Boolean.toString(matches));
return matches;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,10 @@
* @author Robert Stephan
*
*/
public class MCRAndCondition extends MCRAbstractCombinedCondition {
public final class MCRAndCondition extends MCRAbstractCombinedCondition {

public boolean matches(MCRFactsHolder facts) {
return conditions.stream().allMatch(c -> {
boolean matches = c.matches(facts);
debugInfoForMatchingChildElement(c, matches);

return matches;
});
return conditions.stream().allMatch(c -> addDebugInfoIfRequested(c, facts));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@
*/
package org.mycore.access.facts.condition.combined;

import org.jdom2.Element;
import org.mycore.access.facts.MCRFactsHolder;
import org.mycore.access.facts.model.MCRCondition;

/**
* This condition negates its child condition
Expand All @@ -31,22 +29,12 @@
* @author Robert Stephan
*
*/
public class MCRNotCondition extends MCRAbstractCombinedCondition {
public final class MCRNotCondition extends MCRAbstractCombinedCondition {

public boolean matches(MCRFactsHolder facts) {
MCRCondition negatedCondition = conditions.stream().findFirst().get();
boolean result = negatedCondition.matches(facts);
boolean negated = !result;
if (isDebug()) {
Element boundElement = negatedCondition.getBoundElement();
if (boundElement != null) {
boundElement.setAttribute("_matched", Boolean.toString(result));
}

if (this.getBoundElement() != null) {
this.getBoundElement().setAttribute("_matched", Boolean.toString(negated));
}
}
return negated;
return conditions.stream()
.limit(1)
.filter(c -> !addDebugInfoIfRequested(c, facts))
.count() == 1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,9 @@
* @author Robert Stephan
*
*/
public class MCROrCondition extends MCRAbstractCombinedCondition {
public final class MCROrCondition extends MCRAbstractCombinedCondition {

public boolean matches(MCRFactsHolder facts) {
return conditions.stream().anyMatch(c -> {
boolean matches = c.matches(facts);
debugInfoForMatchingChildElement(c, matches);
return matches;
});
return conditions.stream().anyMatch(c -> addDebugInfoIfRequested(c, facts));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* This file is part of *** M y C o R e ***
* See http://www.mycore.de/ for details.
*
* MyCoRe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MyCoRe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MyCoRe. If not, see <http://www.gnu.org/licenses/>.
*/

package org.mycore.access.facts.condition.combined;

import org.mycore.access.facts.MCRFactsHolder;

public final class MCRXorCondition extends MCRAbstractCombinedCondition {
@Override
public boolean matches(MCRFactsHolder facts) {
return conditions.stream()
.filter(c -> addDebugInfoIfRequested(c, facts))
.limit(2)
.count() == 1;
}
}
1 change: 1 addition & 0 deletions mycore-base/src/main/resources/config/mycore.properties
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ MCR.Access.Cache.Size=200

MCR.Access.Facts.Condition.and=org.mycore.access.facts.condition.combined.MCRAndCondition
MCR.Access.Facts.Condition.or=org.mycore.access.facts.condition.combined.MCROrCondition
MCR.Access.Facts.Condition.xor=org.mycore.access.facts.condition.combined.MCRXorCondition
MCR.Access.Facts.Condition.not=org.mycore.access.facts.condition.combined.MCRNotCondition
MCR.Access.Facts.Condition.id=org.mycore.access.facts.condition.fact.MCRStringCondition
MCR.Access.Facts.Condition.target=org.mycore.access.facts.condition.fact.MCRStringCondition
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* This file is part of *** M y C o R e ***
* See http://www.mycore.de/ for details.
*
* MyCoRe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MyCoRe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MyCoRe. If not, see <http://www.gnu.org/licenses/>.
*/

package org.mycore.access.facts.condition.combined;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

class MCRAndConditionTest {

@Test
void matches() {
MCRAndCondition xor=new MCRAndCondition();
xor.add(new MCRTestCondition(()->false));
assertFalse(xor.matches(null));
xor.add(new MCRTestCondition(()->false));
assertFalse(xor.matches(null));
xor.getChildConditions().clear();
xor.add(new MCRTestCondition(()->true));
assertTrue(xor.matches(null));
xor.add(new MCRTestCondition(()->true));
assertTrue(xor.matches(null));
xor.add(new MCRTestCondition(()->false));
assertFalse(xor.matches(null));
xor.add(new MCRTestCondition(() -> {
throw new RuntimeException("Should not be checked");

Check warning on line 43 in mycore-base/src/test/java/org/mycore/access/facts/condition/combined/MCRAndConditionTest.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

mycore-base/src/test/java/org/mycore/access/facts/condition/combined/MCRAndConditionTest.java#L43

Avoid throwing raw exception types.
}));
assertFalse(xor.matches(null));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* This file is part of *** M y C o R e ***
* See http://www.mycore.de/ for details.
*
* MyCoRe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MyCoRe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MyCoRe. If not, see <http://www.gnu.org/licenses/>.
*/

package org.mycore.access.facts.condition.combined;

import static org.junit.jupiter.api.Assertions.assertFalse;

Check notice on line 21 in mycore-base/src/test/java/org/mycore/access/facts/condition/combined/MCRNotConditionTest.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

mycore-base/src/test/java/org/mycore/access/facts/condition/combined/MCRNotConditionTest.java#L21

Unused import 'org.junit.jupiter.api.Assertions.assertFalse'

Check notice on line 21 in mycore-base/src/test/java/org/mycore/access/facts/condition/combined/MCRNotConditionTest.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

mycore-base/src/test/java/org/mycore/access/facts/condition/combined/MCRNotConditionTest.java#L21

Unused import - org.junit.jupiter.api.Assertions.assertFalse.
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

class MCRNotConditionTest {

@Test
void matches() {
MCRNotCondition xor = new MCRNotCondition();
xor.add(new MCRTestCondition(() -> false));
xor.add(new MCRTestCondition(() -> {
throw new RuntimeException("Should not be checked");

Check warning on line 33 in mycore-base/src/test/java/org/mycore/access/facts/condition/combined/MCRNotConditionTest.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

mycore-base/src/test/java/org/mycore/access/facts/condition/combined/MCRNotConditionTest.java#L33

Avoid throwing raw exception types.
}));
assertTrue(xor.matches(null));
xor.getChildConditions().clear();
xor.add(new MCRTestCondition(() -> false));
xor.add(new MCRTestCondition(() -> {
throw new RuntimeException("Should not be checked");
}));
assertTrue(xor.matches(null));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* This file is part of *** M y C o R e ***
* See http://www.mycore.de/ for details.
*
* MyCoRe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MyCoRe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MyCoRe. If not, see <http://www.gnu.org/licenses/>.
*/

package org.mycore.access.facts.condition.combined;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

class MCROrConditionTest {

@Test
void matches() {
MCROrCondition xor = new MCROrCondition();
xor.add(new MCRTestCondition(() -> false));
assertFalse(xor.matches(null));
xor.add(new MCRTestCondition(() -> false));
assertFalse(xor.matches(null));
xor.add(new MCRTestCondition(() -> false));
assertFalse(xor.matches(null));
xor.add(new MCRTestCondition(() -> true));
assertTrue(xor.matches(null));
xor.add(new MCRTestCondition(() -> false));
assertTrue(xor.matches(null));
xor.add(new MCRTestCondition(() -> true));
assertTrue(xor.matches(null));
xor.add(new MCRTestCondition(() -> {
throw new RuntimeException("Should not be checked");

Check warning on line 44 in mycore-base/src/test/java/org/mycore/access/facts/condition/combined/MCROrConditionTest.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

mycore-base/src/test/java/org/mycore/access/facts/condition/combined/MCROrConditionTest.java#L44

Avoid throwing raw exception types.
}));
assertTrue(xor.matches(null));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* This file is part of *** M y C o R e ***
* See http://www.mycore.de/ for details.
*
* MyCoRe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MyCoRe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MyCoRe. If not, see <http://www.gnu.org/licenses/>.
*/

package org.mycore.access.facts.condition.combined;

import org.mycore.access.facts.MCRFactsHolder;
import org.mycore.access.facts.condition.MCRAbstractCondition;

import java.util.function.Supplier;

class MCRTestCondition extends MCRAbstractCondition {
Supplier<Boolean> match;

public MCRTestCondition(Supplier<Boolean> match) {

Check notice on line 29 in mycore-base/src/test/java/org/mycore/access/facts/condition/combined/MCRTestCondition.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

mycore-base/src/test/java/org/mycore/access/facts/condition/combined/MCRTestCondition.java#L29

Redundant 'public' modifier.
this.match = match;
}

@Override
public boolean matches(MCRFactsHolder facts) {
return match.get();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* This file is part of *** M y C o R e ***
* See http://www.mycore.de/ for details.
*
* MyCoRe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MyCoRe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MyCoRe. If not, see <http://www.gnu.org/licenses/>.
*/

package org.mycore.access.facts.condition.combined;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

class MCRXorConditionTest {

@Test
void matches() {
MCRXorCondition xor = new MCRXorCondition();
xor.add(new MCRTestCondition(() -> false));
assertFalse(xor.matches(null));
xor.add(new MCRTestCondition(() -> false));
assertFalse(xor.matches(null));
xor.add(new MCRTestCondition(() -> false));
assertFalse(xor.matches(null));
xor.add(new MCRTestCondition(() -> true));
assertTrue(xor.matches(null));
xor.add(new MCRTestCondition(() -> false));
assertTrue(xor.matches(null));
xor.add(new MCRTestCondition(() -> true));
assertFalse(xor.matches(null));
xor.add(new MCRTestCondition(() -> {
throw new RuntimeException("Should not be checked");

Check warning on line 44 in mycore-base/src/test/java/org/mycore/access/facts/condition/combined/MCRXorConditionTest.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

mycore-base/src/test/java/org/mycore/access/facts/condition/combined/MCRXorConditionTest.java#L44

Avoid throwing raw exception types.
}));
assertFalse(xor.matches(null));
}
}

0 comments on commit 07a0c54

Please sign in to comment.