diff --git a/filterer/README.MD b/filterer/README.MD new file mode 100644 index 000000000..0c03e21a9 --- /dev/null +++ b/filterer/README.MD @@ -0,0 +1,204 @@ +--- # this is so called 'Yaml Front Matter', read up on it here: http://jekyllrb.com/docs/frontmatter/ +layout: pattern +title: Filterer +folder: filterer +permalink: /patterns/filterer/ +description: Design pattern that helps container-like objects to return filtered version of themselves.# short meta description that shows in Google search results +categories: + - Functional +tags: + - Extensibility +--- + +## Name / classification +Filterer + +## Intent +The intent of this design pattern is to introduce a functional interface that will add a functionality for container-like objects to easily return filtered versions of themselves. + +## Explanation +Real world example + +> We are designing a threat(malware) detection system. We can have different types of threats and systems. We have a requirement that +> system should be aware of threats that are present in it. In the design we have to take into consideration that new Threat types can be +> added later. Also there is a requirement that a system can filter itself based on the threats that it possesses (system acts as container-like object for threats). +> + +In plain words + +> We need to be able to filter different types of systems(container-like objects) based on properties of Threats that they contain. +> Adding new properties for Threats should be easy (we still need the ability to filter by those new properties). + +**Programmatic Example** + +To model the threat detection example presented above we introduce `Threat` and `ThreatAwareSystem` interfaces. + +```java +public interface Threat { + String name(); + int id(); + ThreatType type(); +} + +public interface ThreatAwareSystem { + String systemId(); + List threats(); + Filterer filtered(); + +} +``` +Notice the `filtered` method that returns instance of `Filterer` interface which is defined as : +```java +@FunctionalInterface +public interface Filterer { + G by(Predicate predicate); +} +``` +it is used to fulfill the requirement for system to be able to filter itself based on threat properties. +The container-like object (`ThreatAwareSystem` in our case) needs to have a method that returns an instance of `Filterer`. This helper interface gives +ability to covariantly specify a lower bound of contravariant `Predicate` in the subinterfaces of interfaces representing the container-like objects. + +In our example we will be able to pass a predicate that takes `? extends Threat` object and return `? extends ThreatAwareSystem` +from `Filtered::by` method. A simple implementation of `ThreatAwareSystem` : +```java +public class SimpleThreatAwareSystem implements ThreatAwareSystem { + + private final String systemId; + private final ImmutableList issues; + + public SimpleThreatAwareSystem(final String systemId, final List issues) { + this.systemId = systemId; + this.issues = ImmutableList.copyOf(issues); + } + + @Override + public String systemId() { + return systemId; + } + + @Override + public List threats() { + return new ArrayList<>(issues); + } + + @Override + public Filterer filtered() { + return this::filteredGroup; + } + + private ThreatAwareSystem filteredGroup(Predicate predicate) { + return new SimpleThreatAwareSystem(this.systemId, filteredItems(predicate)); + } + + private List filteredItems(Predicate predicate) { + return this.issues.stream() + .filter(predicate) + .collect(Collectors.toList()); + } +} +``` +the `filtered` method is overridden to filter the threats list by given predicate. + +Now if we introduce a new subtype of `Threat` interface that adds probability with which given threat can appear : +```java +public interface ProbableThreat extends Threat { + double probability(); +} +``` +we can also introduce a new interface that represents a system that is aware of threats with their probabilities : +````java +public interface ProbabilisticThreatAwareSystem extends ThreatAwareSystem { + @Override + List threats(); + + @Override + Filterer filtered(); +} +```` +Notice how we override the `filtered` method in `ProbabilisticThreatAwareSystem` and specify different return covariant type +by specifying different generic types. Our interfaces are clean and not cluttered by default implementations. We +we will be able to filter `ProbabilisticThreatAwareSystem` by `ProbableThreat` properties : +```java +public class SimpleProbabilisticThreatAwareSystem implements ProbabilisticThreatAwareSystem { + + private final String systemId; + private final ImmutableList threats; + + public SimpleProbabilisticThreatAwareSystem(final String systemId, final List threats) { + this.systemId = systemId; + this.threats = ImmutableList.copyOf(threats); + } + + @Override + public String systemId() { + return systemId; + } + + @Override + public List threats() { + return threats; + } + + @Override + public Filterer filtered() { + return this::filteredGroup; + } + + private ProbabilisticThreatAwareSystem filteredGroup(final Predicate predicate) { + return new SimpleProbabilisticThreatAwareSystem(this.systemId, filteredItems(predicate)); + } + + private List filteredItems(final Predicate predicate) { + return this.threats.stream() + .filter(predicate) + .collect(Collectors.toList()); + } +} +``` + +Now if we want filter `ThreatAwareSystem` by threat type we can do : +```java +Threat rootkit = new SimpleThreat(ThreatType.ROOTKIT, 1, "Simple-Rootkit"); +Threat trojan = new SimpleThreat(ThreatType.TROJAN, 2, "Simple-Trojan"); +List threats = List.of(rootkit, trojan); + +ThreatAwareSystem threatAwareSystem = new SimpleThreatAwareSystem("System-1", threats); + +ThreatAwareSystem rootkitThreatAwareSystem = threatAwareSystem.filtered() + .by(threat -> threat.type() == ThreatType.ROOTKIT); +``` +or if we want to filter `ProbabilisticThreatAwareSystem` : +```java +ProbableThreat malwareTroyan = new SimpleProbableThreat("Troyan-ArcBomb", 1, ThreatType.TROJAN, 0.99); +ProbableThreat rootkit = new SimpleProbableThreat("Rootkit-System", 2, ThreatType.ROOTKIT, 0.8); +List probableThreats = List.of(malwareTroyan, rootkit); + +ProbabilisticThreatAwareSystem simpleProbabilisticThreatAwareSystem =new SimpleProbabilisticThreatAwareSystem("System-1", probableThreats); + +ProbabilisticThreatAwareSystem filtered = simpleProbabilisticThreatAwareSystem.filtered() + .by(probableThreat -> Double.compare(probableThreat.probability(), 0.99) == 0); +``` +## Class diagram +![Filterer](./etc/filterer.png "Filterer") + +## Applicability +Pattern can be used when working with container-like objects that use subtyping, instead of parametrizing(generics) for extensible class structure. +It enables you to easily extend filtering ability of container-like objects as business requirements change. + +## Tutorials +* [Article about Filterer pattern posted on it's author's blog](https://blog.tlinkowski.pl/2018/filterer-pattern/) +* [Application of Filterer pattern in domain of text analysis](https://www.javacodegeeks.com/2019/02/filterer-pattern-10-steps.html) + +## Known uses +One of the uses is present on the blog presented in [this](https://www.javacodegeeks.com/2019/02/filterer-pattern-10-steps.html) link. +It presents how to use `Filterer` pattern to create text issue analyzer with support for test cases used for unit testing. + +## Consequences +Pros : + * you can easily introduce new subtypes for container-like objects and subtypes for objects that are contained within them and still be able to filter easily be new properties of those new subtypes. + +Cons : + * covariant return types mixed with generics can be sometimes tricky + +## Credits +* Author of the pattern : [Tomasz Linkowski](https://tlinkowski.pl/) \ No newline at end of file diff --git a/filterer/etc/filterer.png b/filterer/etc/filterer.png new file mode 100644 index 000000000..6a6eb059b Binary files /dev/null and b/filterer/etc/filterer.png differ diff --git a/filterer/etc/filterer.urm.puml b/filterer/etc/filterer.urm.puml new file mode 100644 index 000000000..c0bb0b54d --- /dev/null +++ b/filterer/etc/filterer.urm.puml @@ -0,0 +1,96 @@ +@startuml +package com.iluwatar.filterer.domain { + interface Filterer { + + by(Predicate) : G {abstract} + } +} +package com.iluwatar.filterer { + class App { + - LOGGER : Logger {static} + + App() + - filteringSimpleProbableThreats() {static} + - filteringSimpleThreats() {static} + + main(args : String[]) {static} + } +} +package com.iluwatar.filterer.threat { + interface ProbabilisticThreatAwareSystem { + + filtered() : Filterer {abstract} + + threats() : List {abstract} + } + interface ProbableThreat { + + probability() : double {abstract} + } + class SimpleProbabilisticThreatAwareSystem { + - systemId : String + - threats : ImmutableList + + SimpleProbabilisticThreatAwareSystem(systemId : String, threats : List) + + equals(o : Object) : boolean + + filtered() : Filterer + - filteredGroup(predicate : Predicate) : ProbabilisticThreatAwareSystem + - filteredItems(predicate : Predicate) : List + + hashCode() : int + + systemId() : String + + threats() : List + + toString() : String + } + class SimpleProbableThreat { + - probability : double + + SimpleProbableThreat(name : String, id : int, threatType : ThreatType, probability : double) + + equals(o : Object) : boolean + + hashCode() : int + + probability() : double + + toString() : String + } + class SimpleThreat { + - id : int + - name : String + - threatType : ThreatType + + SimpleThreat(threatType : ThreatType, id : int, name : String) + + id() : int + + name() : String + + toString() : String + + type() : ThreatType + } + class SimpleThreatAwareSystem { + - issues : ImmutableList + - systemId : String + + SimpleThreatAwareSystem(systemId : String, issues : List) + + equals(o : Object) : boolean + + filtered() : Filterer + - filteredGroup(predicate : Predicate) : ThreatAwareSystem + - filteredItems(predicate : Predicate) : List + + hashCode() : int + + systemId() : String + + threats() : List + + toString() : String + } + interface Threat { + + id() : int {abstract} + + name() : String {abstract} + + type() : ThreatType {abstract} + } + interface ThreatAwareSystem { + + filtered() : Filterer {abstract} + + systemId() : String {abstract} + + threats() : List {abstract} + } + enum ThreatType { + + ROOTKIT {static} + + TROJAN {static} + + WORM {static} + + valueOf(name : String) : ThreatType {static} + + values() : ThreatType[] {static} + } +} +SimpleThreatAwareSystem --> "-issues" Threat +SimpleThreat --> "-threatType" ThreatType +SimpleProbabilisticThreatAwareSystem --> "-threats" ProbableThreat +ProbabilisticThreatAwareSystem --|> ThreatAwareSystem +ProbableThreat --|> Threat +SimpleProbabilisticThreatAwareSystem ..|> ProbabilisticThreatAwareSystem +SimpleProbableThreat ..|> ProbableThreat +SimpleProbableThreat --|> SimpleThreat +SimpleThreat ..|> Threat +SimpleThreatAwareSystem ..|> ThreatAwareSystem +@enduml \ No newline at end of file diff --git a/filterer/pom.xml b/filterer/pom.xml new file mode 100644 index 000000000..4477332ae --- /dev/null +++ b/filterer/pom.xml @@ -0,0 +1,73 @@ + + + + + java-design-patterns + com.iluwatar + 1.23.0-SNAPSHOT + + 4.0.0 + + filterer + + + + com.google.guava + guava + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + + + + com.iluwatar.filterer.App + + + + + + + + + \ No newline at end of file diff --git a/filterer/src/main/java/com/iluwatar/filterer/App.java b/filterer/src/main/java/com/iluwatar/filterer/App.java new file mode 100644 index 000000000..43de5a646 --- /dev/null +++ b/filterer/src/main/java/com/iluwatar/filterer/App.java @@ -0,0 +1,108 @@ +/* + * 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.filterer; + +import com.iluwatar.filterer.threat.ProbableThreat; +import com.iluwatar.filterer.threat.SimpleProbabilisticThreatAwareSystem; +import com.iluwatar.filterer.threat.SimpleProbableThreat; +import com.iluwatar.filterer.threat.SimpleThreat; +import com.iluwatar.filterer.threat.SimpleThreatAwareSystem; +import com.iluwatar.filterer.threat.Threat; +import com.iluwatar.filterer.threat.ThreatAwareSystem; +import com.iluwatar.filterer.threat.ThreatType; + +import java.util.List; +import java.util.function.Predicate; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This demo class represent how {@link com.iluwatar.filterer.domain.Filterer} pattern is used to + * filter container-like objects to return filtered versions of themselves. The container like + * objects are systems that are aware of threats that they can be vulnerable to. We would like + * to have a way to create copy of different system objects but with filtered threats. + * The thing is to keep it simple if we add new subtype of {@link Threat} + * (for example {@link ProbableThreat}) - we still need to be able to filter by it's properties. + */ +public class App { + + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + + public static void main(String[] args) { + filteringSimpleThreats(); + filteringSimpleProbableThreats(); + } + + /** + * Demonstrates how to filter {@link com.iluwatar.filterer.threat.ProbabilisticThreatAwareSystem} + * based on probability property. The @{@link com.iluwatar.filterer.domain.Filterer#by(Predicate)} + * method is able to use {@link com.iluwatar.filterer.threat.ProbableThreat} + * as predicate argument. + */ + private static void filteringSimpleProbableThreats() { + LOGGER.info(" ### Filtering ProbabilisticThreatAwareSystem by probability ###"); + + var trojanArcBomb = new SimpleProbableThreat("Trojan-ArcBomb", 1, ThreatType.TROJAN, 0.99); + var rootkit = new SimpleProbableThreat("Rootkit-Kernel", 2, ThreatType.ROOTKIT, 0.8); + + List probableThreats = List.of(trojanArcBomb, rootkit); + + var probabilisticThreatAwareSystem = + new SimpleProbabilisticThreatAwareSystem("Sys-1", probableThreats); + + LOGGER.info("Filtering ProbabilisticThreatAwareSystem. Initial : " + + probabilisticThreatAwareSystem); + + //Filtering using filterer + var filteredThreatAwareSystem = probabilisticThreatAwareSystem.filtered() + .by(probableThreat -> Double.compare(probableThreat.probability(), 0.99) == 0); + + LOGGER.info("Filtered by probability = 0.99 : " + filteredThreatAwareSystem); + } + + /** + * Demonstrates how to filter {@link ThreatAwareSystem} based on startingOffset property + * of {@link SimpleThreat}. The @{@link com.iluwatar.filterer.domain.Filterer#by(Predicate)} + * method is able to use {@link Threat} as predicate argument. + */ + private static void filteringSimpleThreats() { + LOGGER.info("### Filtering ThreatAwareSystem by ThreatType ###"); + + var rootkit = new SimpleThreat(ThreatType.ROOTKIT, 1, "Simple-Rootkit"); + var trojan = new SimpleThreat(ThreatType.TROJAN, 2, "Simple-Trojan"); + List threats = List.of(rootkit, trojan); + + var threatAwareSystem = new SimpleThreatAwareSystem("Sys-1", threats); + + LOGGER.info("Filtering ThreatAwareSystem. Initial : " + threatAwareSystem); + + //Filtering using Filterer + var rootkitThreatAwareSystem = threatAwareSystem.filtered() + .by(threat -> threat.type() == ThreatType.ROOTKIT); + + LOGGER.info("Filtered by threatType = ROOTKIT : " + rootkitThreatAwareSystem); + } + +} diff --git a/filterer/src/main/java/com/iluwatar/filterer/domain/Filterer.java b/filterer/src/main/java/com/iluwatar/filterer/domain/Filterer.java new file mode 100644 index 000000000..17970c115 --- /dev/null +++ b/filterer/src/main/java/com/iluwatar/filterer/domain/Filterer.java @@ -0,0 +1,36 @@ +/* + * 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.filterer.domain; + +import java.util.function.Predicate; + +/** + * Filterer helper interface. + * @param type of the container-like object. + * @param type of the elements contained within this container-like object. + */ +@FunctionalInterface +public interface Filterer { + G by(Predicate predicate); +} \ No newline at end of file diff --git a/filterer/src/main/java/com/iluwatar/filterer/threat/ProbabilisticThreatAwareSystem.java b/filterer/src/main/java/com/iluwatar/filterer/threat/ProbabilisticThreatAwareSystem.java new file mode 100644 index 000000000..3a2959828 --- /dev/null +++ b/filterer/src/main/java/com/iluwatar/filterer/threat/ProbabilisticThreatAwareSystem.java @@ -0,0 +1,49 @@ +/* + * 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.filterer.threat; + +import com.iluwatar.filterer.domain.Filterer; + +import java.util.List; + +/** + * Represents system that is aware of it's threats with given probability of their occurrence. + */ +public interface ProbabilisticThreatAwareSystem extends ThreatAwareSystem { + + /** + * {@inheritDoc} + * @return + */ + @Override + List threats(); + + /** + * {@inheritDoc} + * @return + */ + @Override + Filterer filtered(); +} + diff --git a/filterer/src/main/java/com/iluwatar/filterer/threat/ProbableThreat.java b/filterer/src/main/java/com/iluwatar/filterer/threat/ProbableThreat.java new file mode 100644 index 000000000..11e61dbf6 --- /dev/null +++ b/filterer/src/main/java/com/iluwatar/filterer/threat/ProbableThreat.java @@ -0,0 +1,35 @@ +/* + * 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.filterer.threat; + +/** + * Represents threat that might be a threat with given probability. + */ +public interface ProbableThreat extends Threat { + /** + * Returns probability of occurrence of given threat. + * @return probability of occurrence of given threat. + */ + double probability(); +} \ No newline at end of file diff --git a/filterer/src/main/java/com/iluwatar/filterer/threat/SimpleProbabilisticThreatAwareSystem.java b/filterer/src/main/java/com/iluwatar/filterer/threat/SimpleProbabilisticThreatAwareSystem.java new file mode 100644 index 000000000..3991d975e --- /dev/null +++ b/filterer/src/main/java/com/iluwatar/filterer/threat/SimpleProbabilisticThreatAwareSystem.java @@ -0,0 +1,113 @@ +/* + * 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.filterer.threat; + +import com.google.common.collect.ImmutableList; +import com.iluwatar.filterer.domain.Filterer; + +import java.util.List; +import java.util.Objects; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +/** + * {@inheritDoc} + */ +public class SimpleProbabilisticThreatAwareSystem implements ProbabilisticThreatAwareSystem { + + private final String systemId; + private final ImmutableList threats; + + public SimpleProbabilisticThreatAwareSystem( + final String systemId, + final List threats + ) { + this.systemId = systemId; + this.threats = ImmutableList.copyOf(threats); + } + + /** + * {@inheritDoc} + */ + @Override + public String systemId() { + return systemId; + } + + /** + * {@inheritDoc} + */ + @Override + public List threats() { + return threats; + } + + /** + * {@inheritDoc} + */ + @Override + public Filterer filtered() { + return this::filteredGroup; + } + + private ProbabilisticThreatAwareSystem filteredGroup( + final Predicate predicate + ) { + return new SimpleProbabilisticThreatAwareSystem(this.systemId, filteredItems(predicate)); + } + + private List filteredItems( + final Predicate predicate + ) { + return this.threats.stream() + .filter(predicate) + .collect(Collectors.toList()); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + var that = (SimpleProbabilisticThreatAwareSystem) o; + return systemId.equals(that.systemId) + && threats.equals(that.threats); + } + + @Override + public int hashCode() { + return Objects.hash(systemId, threats); + } + + @Override + public String toString() { + return "SimpleProbabilisticThreatAwareSystem{" + + "systemId='" + systemId + '\'' + + ", threats=" + threats + + '}'; + } +} diff --git a/filterer/src/main/java/com/iluwatar/filterer/threat/SimpleProbableThreat.java b/filterer/src/main/java/com/iluwatar/filterer/threat/SimpleProbableThreat.java new file mode 100644 index 000000000..54da07873 --- /dev/null +++ b/filterer/src/main/java/com/iluwatar/filterer/threat/SimpleProbableThreat.java @@ -0,0 +1,79 @@ +/* + * 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.filterer.threat; + +import java.util.Objects; + +/** + * {@inheritDoc} + */ +public class SimpleProbableThreat extends SimpleThreat implements ProbableThreat { + + private final double probability; + + public SimpleProbableThreat(final String name, + final int id, + final ThreatType threatType, + final double probability + ) { + super(threatType, id, name); + this.probability = probability; + } + + /** + * {@inheritDoc} + */ + @Override + public double probability() { + return probability; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + var that = (SimpleProbableThreat) o; + return Double.compare(that.probability, probability) == 0; + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), probability); + } + + @Override + public String toString() { + return "SimpleProbableThreat{" + + "probability=" + probability + + "} " + + super.toString(); + } +} diff --git a/filterer/src/main/java/com/iluwatar/filterer/threat/SimpleThreat.java b/filterer/src/main/java/com/iluwatar/filterer/threat/SimpleThreat.java new file mode 100644 index 000000000..08a8b0e17 --- /dev/null +++ b/filterer/src/main/java/com/iluwatar/filterer/threat/SimpleThreat.java @@ -0,0 +1,101 @@ +/* + * 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.filterer.threat; + +import java.util.Objects; + +/** + * Represents a simple threat. + */ +public class SimpleThreat implements Threat { + + private final ThreatType threatType; + private final int id; + private final String name; + + /** + * Constructor. + * + * @param threatType {@link ThreatType}. + * @param id threat id. + * @param name threat name. + */ + public SimpleThreat(final ThreatType threatType, final int id, String name) { + this.threatType = threatType; + this.id = id; + this.name = name; + } + + /** + * {@inheritDoc} + */ + @Override + public String name() { + return name; + } + + /** + * {@inheritDoc} + */ + @Override + public int id() { + return id; + } + + /** + * {@inheritDoc} + */ + @Override + public ThreatType type() { + return threatType; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + var that = (SimpleThreat) o; + return id == that.id + && threatType == that.threatType + && Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + return Objects.hash(threatType, id, name); + } + + @Override + public String toString() { + return "SimpleThreat{" + + "threatType=" + threatType + + ", id=" + id + + ", name='" + name + '\'' + + '}'; + } +} diff --git a/filterer/src/main/java/com/iluwatar/filterer/threat/SimpleThreatAwareSystem.java b/filterer/src/main/java/com/iluwatar/filterer/threat/SimpleThreatAwareSystem.java new file mode 100644 index 000000000..f1dec40ae --- /dev/null +++ b/filterer/src/main/java/com/iluwatar/filterer/threat/SimpleThreatAwareSystem.java @@ -0,0 +1,107 @@ +/* + * 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.filterer.threat; + +import com.google.common.collect.ImmutableList; +import com.iluwatar.filterer.domain.Filterer; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +/** + * {@inheritDoc} + */ +public class SimpleThreatAwareSystem implements ThreatAwareSystem { + + private final String systemId; + private final ImmutableList issues; + + public SimpleThreatAwareSystem(final String systemId, final List issues) { + this.systemId = systemId; + this.issues = ImmutableList.copyOf(issues); + } + + /** + * {@inheritDoc} + */ + @Override + public String systemId() { + return systemId; + } + + /** + * {@inheritDoc} + */ + @Override + public List threats() { + return new ArrayList<>(issues); + } + + /** + * {@inheritDoc} + */ + @Override + public Filterer filtered() { + return this::filteredGroup; + } + + private ThreatAwareSystem filteredGroup(Predicate predicate) { + return new SimpleThreatAwareSystem(this.systemId, filteredItems(predicate)); + } + + private List filteredItems(Predicate predicate) { + return this.issues.stream() + .filter(predicate) + .collect(Collectors.toList()); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + var that = (SimpleThreatAwareSystem) o; + return systemId.equals(that.systemId) + && issues.equals(that.issues); + } + + @Override + public int hashCode() { + return Objects.hash(systemId, issues); + } + + @Override + public String toString() { + return "SimpleThreatAwareSystem{" + + "systemId='" + systemId + + '\'' + ", issues=" + issues + + '}'; + } +} diff --git a/filterer/src/main/java/com/iluwatar/filterer/threat/Threat.java b/filterer/src/main/java/com/iluwatar/filterer/threat/Threat.java new file mode 100644 index 000000000..515b59332 --- /dev/null +++ b/filterer/src/main/java/com/iluwatar/filterer/threat/Threat.java @@ -0,0 +1,49 @@ +/* + * 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.filterer.threat; + +/** + * Represents a threat that can be detected in given system. + */ +public interface Threat { + /** + * Returns name of the threat. + * + * @return value representing name of the threat. + */ + String name(); + + /** + * Returns unique id of the threat. + * + * @return value representing threat id. + */ + int id(); + + /** + * Returns threat type. + * @return {@link ThreatType} + */ + ThreatType type(); +} diff --git a/filterer/src/main/java/com/iluwatar/filterer/threat/ThreatAwareSystem.java b/filterer/src/main/java/com/iluwatar/filterer/threat/ThreatAwareSystem.java new file mode 100644 index 000000000..b889d537d --- /dev/null +++ b/filterer/src/main/java/com/iluwatar/filterer/threat/ThreatAwareSystem.java @@ -0,0 +1,55 @@ +/* + * 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.filterer.threat; + +import com.iluwatar.filterer.domain.Filterer; + +import java.util.List; + +/** + * Represents system that is aware of threats that are present in it. + */ +public interface ThreatAwareSystem { + + /** + * Returns the system id. + * + * @return system id. + */ + String systemId(); + + /** + * Returns list of threats for this system. + * @return list of threats for this system. + */ + List threats(); + + /** + * Returns the instance of {@link Filterer} helper interface that allows to covariantly + * specify lower bound for predicate that we want to filter by. + * @return an instance of {@link Filterer} helper interface. + */ + Filterer filtered(); + +} diff --git a/filterer/src/main/java/com/iluwatar/filterer/threat/ThreatType.java b/filterer/src/main/java/com/iluwatar/filterer/threat/ThreatType.java new file mode 100644 index 000000000..5f9a152a8 --- /dev/null +++ b/filterer/src/main/java/com/iluwatar/filterer/threat/ThreatType.java @@ -0,0 +1,26 @@ +/* + * 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.filterer.threat; + +public enum ThreatType { TROJAN, WORM, ROOTKIT } diff --git a/filterer/src/test/java/com/iluwatar/filterer/AppTest.java b/filterer/src/test/java/com/iluwatar/filterer/AppTest.java new file mode 100644 index 000000000..551ebcc18 --- /dev/null +++ b/filterer/src/test/java/com/iluwatar/filterer/AppTest.java @@ -0,0 +1,33 @@ +/* + * 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.filterer; + +import org.junit.jupiter.api.Test; + +class AppTest { + @Test + void shouldLaunchApp() { + App.main(new String[]{}); + } +} \ No newline at end of file diff --git a/filterer/src/test/java/com/iluwatar/filterer/threat/SimpleProbabilisticThreatAwareSystemTest.java b/filterer/src/test/java/com/iluwatar/filterer/threat/SimpleProbabilisticThreatAwareSystemTest.java new file mode 100644 index 000000000..2f14ca057 --- /dev/null +++ b/filterer/src/test/java/com/iluwatar/filterer/threat/SimpleProbabilisticThreatAwareSystemTest.java @@ -0,0 +1,51 @@ +/* + * 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.filterer.threat; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class SimpleProbabilisticThreatAwareSystemTest { + @Test + void shouldFilterByProbability() { + //given + var trojan = new SimpleProbableThreat("Troyan-ArcBomb", 1, ThreatType.TROJAN, 0.99); + var rootkit = new SimpleProbableThreat("Rootkit-System", 2, ThreatType.ROOTKIT, 0.8); + List probableThreats = List.of(trojan, rootkit); + + var simpleProbabilisticThreatAwareSystem = + new SimpleProbabilisticThreatAwareSystem("System-1", probableThreats); + + //when + var filtered = simpleProbabilisticThreatAwareSystem.filtered() + .by(probableThreat -> Double.compare(probableThreat.probability(), 0.99) == 0); + + //then + assertEquals(filtered.threats().size(), 1); + assertEquals(filtered.threats().get(0), trojan); + } +} \ No newline at end of file diff --git a/filterer/src/test/java/com/iluwatar/filterer/threat/SimpleThreatAwareSystemTest.java b/filterer/src/test/java/com/iluwatar/filterer/threat/SimpleThreatAwareSystemTest.java new file mode 100644 index 000000000..ea918c9ec --- /dev/null +++ b/filterer/src/test/java/com/iluwatar/filterer/threat/SimpleThreatAwareSystemTest.java @@ -0,0 +1,50 @@ +/* + * 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.filterer.threat; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class SimpleThreatAwareSystemTest { + @Test + void shouldFilterByThreatType() { + //given + var rootkit = new SimpleThreat(ThreatType.ROOTKIT, 1, "Simple-Rootkit"); + var trojan = new SimpleThreat(ThreatType.TROJAN, 2, "Simple-Trojan"); + List threats = List.of(rootkit, trojan); + + var threatAwareSystem = new SimpleThreatAwareSystem("System-1", threats); + + //when + var rootkitThreatAwareSystem = threatAwareSystem.filtered() + .by(threat -> threat.type() == ThreatType.ROOTKIT); + + //then + assertEquals(rootkitThreatAwareSystem.threats().size(), 1); + assertEquals(rootkitThreatAwareSystem.threats().get(0), rootkit); + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 662672f0f..1275ce115 100644 --- a/pom.xml +++ b/pom.xml @@ -194,6 +194,7 @@ strangler arrange-act-assert transaction-script + filterer