Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Filters implemented for the new Aggregation logic
Tree filtering doesn't work yet - it only filters the top-level nodes, which is not particularly useful :) Main reason is that I think there are (at least) 2 ways for a tree to be filtered and pruned, and these need to be distinguished in the filtering algorithm, since it depends on the type of filter. Will start on that now...
- Loading branch information
rx
committed
Jan 19, 2017
1 parent
dcfb993
commit 0fcbab7
Showing
51 changed files
with
1,148 additions
and
871 deletions.
There are no files selected for viewing
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
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
156 changes: 156 additions & 0 deletions
156
src/main/java/com/insightfullogic/honest_profiler/core/aggregation/filter/Comparison.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,156 @@ | ||
package com.insightfullogic.honest_profiler.core.aggregation.filter; | ||
|
||
import static java.util.regex.Pattern.compile; | ||
|
||
import java.util.function.Function; | ||
import java.util.function.Predicate; | ||
import java.util.regex.Pattern; | ||
|
||
public enum Comparison | ||
{ | ||
EQUALS_NR("="), | ||
GT(">"), | ||
LT("<"), | ||
GE(">="), | ||
LE("<="), | ||
EQUALS_STR("Equals"), | ||
STARTS_WITH("Starts With"), | ||
ENDS_WITH("Ends With"), | ||
CONTAINS("Contains"), | ||
NOT_CONTAINS("Doesn't Contain"), | ||
MATCHES("Matches"); | ||
|
||
// A bit hacky : can't define this AND use it in ValueType, since it needs to be used there before it can be | ||
// defined (Enums can be sooo tricky :( ). So it got placed here semi-arbitrarily... | ||
public static final Function<String, ?> PCT_INTERPRETER = str -> Double.parseDouble(str) / 100.; | ||
|
||
public static final Comparison[] NUMBER_COMPARISONS = new Comparison[] | ||
{ EQUALS_NR, GT, LT, GE, LE }; | ||
|
||
public static final Comparison[] STRING_COMPARISONS = new Comparison[] | ||
{ EQUALS_STR, STARTS_WITH, ENDS_WITH, CONTAINS, MATCHES }; | ||
|
||
public static Predicate<Double> getPredicate(Comparison comparison, Double value) | ||
{ | ||
switch (comparison) | ||
{ | ||
case EQUALS_NR: | ||
return nr -> nr == value; | ||
case GT: | ||
return nr -> nr > value; | ||
case LT: | ||
return nr -> nr < value; | ||
case GE: | ||
return nr -> nr >= value; | ||
case LE: | ||
return nr -> nr <= value; | ||
default: | ||
break; | ||
} | ||
throw new RuntimeException( | ||
"Comparison type " + comparison + " is not compatible with the value type Double."); | ||
} | ||
|
||
public static Predicate<Integer> getPredicate(Comparison comparison, Integer value) | ||
{ | ||
switch (comparison) | ||
{ | ||
case EQUALS_NR: | ||
return nr -> nr == value; | ||
case GT: | ||
return nr -> nr > value; | ||
case LT: | ||
return nr -> nr < value; | ||
case GE: | ||
return nr -> nr >= value; | ||
case LE: | ||
return nr -> nr <= value; | ||
default: | ||
break; | ||
} | ||
throw new RuntimeException( | ||
"Comparison type " + comparison + " is not compatible with the value type Integer."); | ||
} | ||
|
||
public static Predicate<Long> getPredicate(Comparison comparison, Long value) | ||
{ | ||
switch (comparison) | ||
{ | ||
case EQUALS_NR: | ||
return nr -> nr == value; | ||
case GT: | ||
return nr -> nr > value; | ||
case LT: | ||
return nr -> nr < value; | ||
case GE: | ||
return nr -> nr >= value; | ||
case LE: | ||
return nr -> nr <= value; | ||
default: | ||
break; | ||
} | ||
throw new RuntimeException( | ||
"Comparison type " + comparison + " is not compatible with the value type Long."); | ||
} | ||
|
||
public static Predicate<String> getPredicate(Comparison comparison, String value) | ||
{ | ||
switch (comparison) | ||
{ | ||
case EQUALS_STR: | ||
return str -> str.equals(value); | ||
case STARTS_WITH: | ||
return str -> str.startsWith(value); | ||
case ENDS_WITH: | ||
return str -> str.endsWith(value); | ||
case CONTAINS: | ||
return str -> str.contains(value); | ||
case NOT_CONTAINS: | ||
return str -> !str.contains(value); | ||
case MATCHES: | ||
Pattern pattern = compile(value); | ||
return str -> pattern.matcher(str).matches(); | ||
default: | ||
break; | ||
} | ||
|
||
throw new RuntimeException( | ||
"Comparison type " + comparison + " is not compatible with the value type String."); | ||
} | ||
|
||
private String name; | ||
|
||
private Comparison(String name) | ||
{ | ||
this.name = name; | ||
} | ||
|
||
@SuppressWarnings("unchecked") | ||
public <T> Predicate<T> getPredicate(T value) | ||
{ | ||
if (value instanceof Double) | ||
{ | ||
return (Predicate<T>) Comparison.getPredicate(this, (Double) value); | ||
} | ||
if (value instanceof Integer) | ||
{ | ||
return (Predicate<T>) Comparison.getPredicate(this, (Integer) value); | ||
} | ||
if (value instanceof Long) | ||
{ | ||
return (Predicate<T>) Comparison.getPredicate(this, (Long) value); | ||
} | ||
if (value instanceof String) | ||
{ | ||
return (Predicate<T>) Comparison.getPredicate(this, (String) value); | ||
} | ||
throw new RuntimeException( | ||
"Comparison type " + this + " is not compatible with the value type String."); | ||
} | ||
|
||
@Override | ||
public String toString() | ||
{ | ||
return name; | ||
} | ||
} |
76 changes: 76 additions & 0 deletions
76
src/main/java/com/insightfullogic/honest_profiler/core/aggregation/filter/FilterItem.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,76 @@ | ||
package com.insightfullogic.honest_profiler.core.aggregation.filter; | ||
|
||
import java.util.function.Function; | ||
import java.util.function.Predicate; | ||
|
||
import com.insightfullogic.honest_profiler.core.aggregation.result.ItemType; | ||
|
||
public class FilterItem<T, U> | ||
{ | ||
private Target target; | ||
private Comparison comparison; | ||
private U value; | ||
|
||
public FilterItem(Target target, Comparison comparison, U value) | ||
{ | ||
super(); | ||
|
||
this.target = target; | ||
this.comparison = comparison; | ||
this.value = value; | ||
} | ||
|
||
public Comparison getComparison() | ||
{ | ||
return comparison; | ||
} | ||
|
||
public void setComparison(Comparison comparison) | ||
{ | ||
this.comparison = comparison; | ||
} | ||
|
||
public Target getTarget() | ||
{ | ||
return target; | ||
} | ||
|
||
public void setTarget(Target target) | ||
{ | ||
this.target = target; | ||
} | ||
|
||
public U getValue() | ||
{ | ||
return value; | ||
} | ||
|
||
public void setValue(U value) | ||
{ | ||
this.value = value; | ||
} | ||
|
||
public Predicate<T> toFilter(ItemType type) | ||
{ | ||
return new FilterPredicate<>(type, target, comparison, value); | ||
} | ||
|
||
static class FilterPredicate<T, U> implements Predicate<T> | ||
{ | ||
|
||
private Function<T, U> extractor; | ||
private Predicate<U> comparer; | ||
|
||
FilterPredicate(ItemType type, Target target, Comparison comparison, U value) | ||
{ | ||
extractor = target.<T, U>getExtractor(type); | ||
comparer = comparison.getPredicate(value); | ||
} | ||
|
||
@Override | ||
public boolean test(T t) | ||
{ | ||
return comparer.test(extractor.apply(t)); | ||
} | ||
} | ||
} |
80 changes: 80 additions & 0 deletions
80
...java/com/insightfullogic/honest_profiler/core/aggregation/filter/FilterSpecification.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,80 @@ | ||
package com.insightfullogic.honest_profiler.core.aggregation.filter; | ||
|
||
import static com.insightfullogic.honest_profiler.core.aggregation.filter.Comparison.CONTAINS; | ||
import static com.insightfullogic.honest_profiler.core.aggregation.filter.Comparison.NOT_CONTAINS; | ||
import static com.insightfullogic.honest_profiler.core.aggregation.filter.Target.FQMN; | ||
import static java.util.Collections.emptyList; | ||
|
||
import java.util.List; | ||
import java.util.function.Predicate; | ||
|
||
import com.insightfullogic.honest_profiler.core.aggregation.result.ItemType; | ||
|
||
public class FilterSpecification<T> | ||
{ | ||
private ItemType type; | ||
private boolean hideErrors; | ||
private String quickFilter; | ||
|
||
private List<FilterItem<T, ?>> filters; | ||
|
||
public FilterSpecification(ItemType type) | ||
{ | ||
super(); | ||
this.type = type; | ||
filters = emptyList(); | ||
} | ||
|
||
public FilterSpecification(ItemType type, boolean hideErrors, List<FilterItem<T, ?>> filters) | ||
{ | ||
super(); | ||
|
||
this.type = type; | ||
this.hideErrors = hideErrors; | ||
this.filters = filters; | ||
} | ||
|
||
public boolean isHideErrors() | ||
{ | ||
return hideErrors; | ||
} | ||
|
||
public void setQuickFilter(String value) | ||
{ | ||
this.quickFilter = value; | ||
} | ||
|
||
public Predicate<T> getFilter() | ||
{ | ||
Predicate<T> result = hideErrors ? errorFilter() : null; | ||
if (quickFilter != null && !quickFilter.isEmpty()) | ||
{ | ||
result = result == null ? quickFilter() : result.and(quickFilter()); | ||
} | ||
if (filters.size() > 0) | ||
{ | ||
result = result == null ? filter() : result.and(filter()); | ||
} | ||
return result == null ? str -> true : result; | ||
} | ||
|
||
public boolean isFiltering() | ||
{ | ||
return hideErrors || filters.size() > 0; | ||
} | ||
|
||
private Predicate<T> filter() | ||
{ | ||
return filters.stream().map(item -> item.toFilter(type)).reduce(Predicate::and).get(); | ||
} | ||
|
||
private Predicate<T> quickFilter() | ||
{ | ||
return new FilterItem.FilterPredicate<T, String>(type, FQMN, CONTAINS, quickFilter); | ||
} | ||
|
||
private final Predicate<T> errorFilter() | ||
{ | ||
return new FilterItem.FilterPredicate<T, String>(type, FQMN, NOT_CONTAINS, "[ERR="); | ||
} | ||
} |
Oops, something went wrong.