Skip to content

Commit

Permalink
Filters implemented for the new Aggregation logic
Browse files Browse the repository at this point in the history
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
Show file tree
Hide file tree
Showing 51 changed files with 1,148 additions and 871 deletions.
Expand Up @@ -7,8 +7,10 @@
import com.insightfullogic.honest_profiler.core.aggregation.aggregator.FlatByFqmnAggregator;
import com.insightfullogic.honest_profiler.core.aggregation.aggregator.TreeByFqmnAggregator;
import com.insightfullogic.honest_profiler.core.aggregation.result.Aggregation;
import com.insightfullogic.honest_profiler.core.aggregation.result.Entry;
import com.insightfullogic.honest_profiler.core.aggregation.result.Node;
import com.insightfullogic.honest_profiler.core.aggregation.result.straight.Entry;
import com.insightfullogic.honest_profiler.core.aggregation.result.straight.Flat;
import com.insightfullogic.honest_profiler.core.aggregation.result.straight.Node;
import com.insightfullogic.honest_profiler.core.aggregation.result.straight.Tree;
import com.insightfullogic.honest_profiler.core.profiles.lean.LeanNode;
import com.insightfullogic.honest_profiler.core.profiles.lean.LeanProfile;
import com.insightfullogic.honest_profiler.core.profiles.lean.NumericInfo;
Expand Down Expand Up @@ -60,17 +62,17 @@ public Map<String, FqmnLink> getFqmnLinks()
}

@SuppressWarnings("unchecked")
public Aggregation<String, Entry<String>> getFlatAggregation()
public Flat<String> getFlat()
{
cachedAggregations.putIfAbsent(flatAggregator, flatAggregator.aggregate(this, profileNode));
return (Aggregation<String, Entry<String>>) cachedAggregations.get(flatAggregator);
return (Flat<String>) cachedAggregations.get(flatAggregator);
}

@SuppressWarnings("unchecked")
public Aggregation<String, Node<String>> getTreeAggregation()
public Tree<String> getTree()
{
cachedAggregations.putIfAbsent(treeAggregator, treeAggregator.aggregate(this, profileNode));
return (Aggregation<String, Node<String>>) cachedAggregations.get(treeAggregator);
return (Tree<String>) cachedAggregations.get(treeAggregator);
}

private void aggregateTopLevel()
Expand Down
Expand Up @@ -5,8 +5,8 @@
import java.util.List;

import com.insightfullogic.honest_profiler.core.aggregation.AggregationProfile;
import com.insightfullogic.honest_profiler.core.aggregation.result.Entry;
import com.insightfullogic.honest_profiler.core.aggregation.result.Flat;
import com.insightfullogic.honest_profiler.core.aggregation.result.straight.Entry;
import com.insightfullogic.honest_profiler.core.aggregation.result.straight.Flat;
import com.insightfullogic.honest_profiler.core.profiles.lean.LeanNode;
import com.insightfullogic.honest_profiler.core.profiles.lean.NumericInfo;

Expand Down
Expand Up @@ -9,9 +9,9 @@
import java.util.stream.Collector;

import com.insightfullogic.honest_profiler.core.aggregation.AggregationProfile;
import com.insightfullogic.honest_profiler.core.aggregation.result.Entry;
import com.insightfullogic.honest_profiler.core.aggregation.result.Node;
import com.insightfullogic.honest_profiler.core.aggregation.result.Tree;
import com.insightfullogic.honest_profiler.core.aggregation.result.straight.Entry;
import com.insightfullogic.honest_profiler.core.aggregation.result.straight.Node;
import com.insightfullogic.honest_profiler.core.aggregation.result.straight.Tree;
import com.insightfullogic.honest_profiler.core.profiles.lean.LeanNode;
import com.insightfullogic.honest_profiler.core.profiles.lean.LeanProfile;

Expand Down
@@ -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;
}
}
@@ -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));
}
}
}
@@ -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=");
}
}

0 comments on commit 0fcbab7

Please sign in to comment.