Adding composite specification (Issue#1093) (#1094)
* Resolution proposition to Issue#1055 (UML diagram left to do) * Deciding not to modify the UML diagram for now * Resolution proposition to Issue#1093 * Code reformatting
This commit is contained in:
committed by
Ilkka Seppälä
parent
19b129c28e
commit
73f9b8bef1
@ -31,9 +31,10 @@ import com.iluwatar.specification.creature.Octopus;
|
||||
import com.iluwatar.specification.creature.Shark;
|
||||
import com.iluwatar.specification.creature.Troll;
|
||||
import com.iluwatar.specification.property.Color;
|
||||
import com.iluwatar.specification.property.Mass;
|
||||
import com.iluwatar.specification.property.Movement;
|
||||
import com.iluwatar.specification.selector.AbstractSelector;
|
||||
import com.iluwatar.specification.selector.ColorSelector;
|
||||
import com.iluwatar.specification.selector.MassEqualSelector;
|
||||
import com.iluwatar.specification.selector.MassGreaterThanSelector;
|
||||
import com.iluwatar.specification.selector.MassSmallerThanOrEqSelector;
|
||||
import com.iluwatar.specification.selector.MovementSelector;
|
||||
@ -77,13 +78,8 @@ public class App {
|
||||
List<Creature> darkCreatures =
|
||||
creatures.stream().filter(new ColorSelector(Color.DARK)).collect(Collectors.toList());
|
||||
darkCreatures.forEach(c -> LOGGER.info(c.toString()));
|
||||
// find all red and flying creatures
|
||||
LOGGER.info("Find all red and flying creatures");
|
||||
List<Creature> redAndFlyingCreatures =
|
||||
creatures.stream()
|
||||
.filter(new ColorSelector(Color.RED).and(new MovementSelector(Movement.FLYING)))
|
||||
.collect(Collectors.toList());
|
||||
redAndFlyingCreatures.forEach(c -> LOGGER.info(c.toString()));
|
||||
|
||||
LOGGER.info("\n");
|
||||
// so-called "parameterized" specification
|
||||
LOGGER.info("Demonstrating parameterized specification :");
|
||||
// find all creatures heavier than 500kg
|
||||
@ -98,5 +94,26 @@ public class App {
|
||||
creatures.stream().filter(new MassSmallerThanOrEqSelector(500.0))
|
||||
.collect(Collectors.toList());
|
||||
lightCreatures.forEach(c -> LOGGER.info(c.toString()));
|
||||
|
||||
LOGGER.info("\n");
|
||||
// so-called "composite" specification
|
||||
LOGGER.info("Demonstrating composite specification :");
|
||||
// find all red and flying creatures
|
||||
LOGGER.info("Find all red and flying creatures");
|
||||
List<Creature> redAndFlyingCreatures =
|
||||
creatures.stream()
|
||||
.filter(new ColorSelector(Color.RED).and(new MovementSelector(Movement.FLYING)))
|
||||
.collect(Collectors.toList());
|
||||
redAndFlyingCreatures.forEach(c -> LOGGER.info(c.toString()));
|
||||
// find all creatures dark or red, non-swimming, and heavier than or equal to 400kg
|
||||
LOGGER.info("Find all scary creatures");
|
||||
AbstractSelector<Creature> scaryCreaturesSelector = new ColorSelector(Color.DARK)
|
||||
.or(new ColorSelector(Color.RED)).and(new MovementSelector(Movement.SWIMMING).not())
|
||||
.and(new MassGreaterThanSelector(400.0).or(new MassEqualSelector(400.0)));
|
||||
List<Creature> scaryCreatures =
|
||||
creatures.stream()
|
||||
.filter(scaryCreaturesSelector)
|
||||
.collect(Collectors.toList());
|
||||
scaryCreatures.forEach(c -> LOGGER.info(c.toString()));
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,9 @@
|
||||
|
||||
package com.iluwatar.specification.property;
|
||||
|
||||
/** Mass property. */
|
||||
/**
|
||||
* Mass property.
|
||||
*/
|
||||
public class Mass {
|
||||
|
||||
private double value;
|
||||
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.specification.selector;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Base class for selectors.
|
||||
*/
|
||||
public abstract class AbstractSelector<T> implements Predicate<T> {
|
||||
|
||||
public AbstractSelector<T> and(AbstractSelector<T> other) {
|
||||
return new ConjunctionSelector<>(this, other);
|
||||
}
|
||||
|
||||
public AbstractSelector<T> or(AbstractSelector<T> other) {
|
||||
return new DisjunctionSelector<>(this, other);
|
||||
}
|
||||
|
||||
public AbstractSelector<T> not() {
|
||||
return new NegationSelector<>(this);
|
||||
}
|
||||
}
|
@ -25,12 +25,11 @@ package com.iluwatar.specification.selector;
|
||||
|
||||
import com.iluwatar.specification.creature.Creature;
|
||||
import com.iluwatar.specification.property.Color;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Color selector.
|
||||
*/
|
||||
public class ColorSelector implements Predicate<Creature> {
|
||||
public class ColorSelector extends AbstractSelector<Creature> {
|
||||
|
||||
private final Color color;
|
||||
|
||||
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.specification.selector;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A Selector defined as the conjunction (AND) of other (leaf) selectors.
|
||||
*/
|
||||
public class ConjunctionSelector<T> extends AbstractSelector<T> {
|
||||
|
||||
private List<AbstractSelector<T>> leafComponents;
|
||||
|
||||
@SafeVarargs
|
||||
ConjunctionSelector(AbstractSelector<T>... selectors) {
|
||||
this.leafComponents = List.of(selectors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if *all* selectors pass the test.
|
||||
*/
|
||||
@Override
|
||||
public boolean test(T t) {
|
||||
return leafComponents.stream().allMatch(comp -> (comp.test(t)));
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.specification.selector;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A Selector defined as the disjunction (OR) of other (leaf) selectors.
|
||||
*/
|
||||
public class DisjunctionSelector<T> extends AbstractSelector<T> {
|
||||
|
||||
private List<AbstractSelector<T>> leafComponents;
|
||||
|
||||
@SafeVarargs
|
||||
DisjunctionSelector(AbstractSelector<T>... selectors) {
|
||||
this.leafComponents = List.of(selectors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if *at least one* selector passes the test.
|
||||
*/
|
||||
@Override
|
||||
public boolean test(T t) {
|
||||
return leafComponents.stream().anyMatch(comp -> comp.test(t));
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.specification.selector;
|
||||
|
||||
import com.iluwatar.specification.creature.Creature;
|
||||
import com.iluwatar.specification.property.Mass;
|
||||
|
||||
/**
|
||||
* Mass selector for values exactly equal than the parameter.
|
||||
*/
|
||||
public class MassEqualSelector extends AbstractSelector<Creature> {
|
||||
|
||||
private final Mass mass;
|
||||
|
||||
/**
|
||||
* The use of a double as a parameter will spare some typing when instantiating this class.
|
||||
*/
|
||||
public MassEqualSelector(double mass) {
|
||||
this.mass = new Mass(mass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Creature t) {
|
||||
return t.getMass().equals(mass);
|
||||
}
|
||||
}
|
@ -25,14 +25,17 @@ package com.iluwatar.specification.selector;
|
||||
|
||||
import com.iluwatar.specification.creature.Creature;
|
||||
import com.iluwatar.specification.property.Mass;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/** Mass selector for values greater than the parameter. */
|
||||
public class MassGreaterThanSelector implements Predicate<Creature> {
|
||||
/**
|
||||
* Mass selector for values greater than the parameter.
|
||||
*/
|
||||
public class MassGreaterThanSelector extends AbstractSelector<Creature> {
|
||||
|
||||
private final Mass mass;
|
||||
|
||||
/** The use of a double as a parameter will spare some typing when instantiating this class. */
|
||||
/**
|
||||
* The use of a double as a parameter will spare some typing when instantiating this class.
|
||||
*/
|
||||
public MassGreaterThanSelector(double mass) {
|
||||
this.mass = new Mass(mass);
|
||||
}
|
||||
|
@ -25,14 +25,17 @@ package com.iluwatar.specification.selector;
|
||||
|
||||
import com.iluwatar.specification.creature.Creature;
|
||||
import com.iluwatar.specification.property.Mass;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/** Mass selector for values smaller or equal to the parameter. */
|
||||
public class MassSmallerThanOrEqSelector implements Predicate<Creature> {
|
||||
/**
|
||||
* Mass selector for values smaller or equal to the parameter.
|
||||
*/
|
||||
public class MassSmallerThanOrEqSelector extends AbstractSelector<Creature> {
|
||||
|
||||
private final Mass mass;
|
||||
|
||||
/** The use of a double as a parameter will spare some typing when instantiating this class. */
|
||||
/**
|
||||
* The use of a double as a parameter will spare some typing when instantiating this class.
|
||||
*/
|
||||
public MassSmallerThanOrEqSelector(double mass) {
|
||||
this.mass = new Mass(mass);
|
||||
}
|
||||
|
@ -25,12 +25,11 @@ package com.iluwatar.specification.selector;
|
||||
|
||||
import com.iluwatar.specification.creature.Creature;
|
||||
import com.iluwatar.specification.property.Movement;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Movement selector.
|
||||
*/
|
||||
public class MovementSelector implements Predicate<Creature> {
|
||||
public class MovementSelector extends AbstractSelector<Creature> {
|
||||
|
||||
private final Movement movement;
|
||||
|
||||
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.specification.selector;
|
||||
|
||||
|
||||
/**
|
||||
* A Selector defined as the negation (NOT) of a (leaf) selectors. This is of course only useful
|
||||
* when used in combination with other composite selectors.
|
||||
*/
|
||||
public class NegationSelector<T> extends AbstractSelector<T> {
|
||||
|
||||
private AbstractSelector<T> component;
|
||||
|
||||
NegationSelector(AbstractSelector<T> selector) {
|
||||
this.component = selector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the selector fails the test (yes).
|
||||
*/
|
||||
@Override
|
||||
public boolean test(T t) {
|
||||
return !(component.test(t));
|
||||
}
|
||||
}
|
@ -25,12 +25,11 @@ package com.iluwatar.specification.selector;
|
||||
|
||||
import com.iluwatar.specification.creature.Creature;
|
||||
import com.iluwatar.specification.property.Size;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Size selector.
|
||||
*/
|
||||
public class SizeSelector implements Predicate<Creature> {
|
||||
public class SizeSelector extends AbstractSelector<Creature> {
|
||||
|
||||
private final Size size;
|
||||
|
||||
|
Reference in New Issue
Block a user