public static Multiset<Row> flowTracesToRows( SortedMap<Flow, List<Trace>> flowTraces, int maxTraces) { Multiset<Row> rows = LinkedHashMultiset.create(); for (Map.Entry<Flow, List<Trace>> flowTrace : flowTraces.entrySet()) { List<Trace> traces = flowTrace.getValue(); List<Trace> prunedTraces = TracePruner.prune(traces, maxTraces); rows.add( Row.of( COL_FLOW, flowTrace.getKey(), COL_TRACES, prunedTraces, COL_TRACE_COUNT, traces.size())); } return rows; }
public static List<Trace> prune(List<Trace> traces, int maxSize) { if (traces.size() <= maxSize) { return traces; } return new TracePruner(traces).prune(maxSize); }
private List<Trace> prune(int maxSize) { List<Trace> usedTraces = new ArrayList<>(); while (usedTraces.size() < maxSize) { if (!_unpickedDispositions.isEmpty()) { usedTraces.add(chooseTraceByDisposition()); } else if (!_unpickedNodes.isEmpty()) { usedTraces.add(chooseTraceByNode()); } else { _traces.stream() .filter(trace -> !_pickedTraces.contains(trace)) .limit(maxSize - usedTraces.size()) .forEach(usedTraces::add); break; } } return usedTraces; }
private Trace chooseTraceByDisposition() { Trace t = _unpickedDispositions.stream() .flatMap(disposition -> _dispositionTraces.get(disposition).stream()) .filter(trace -> !_pickedTraces.contains(trace)) .findFirst() .orElseThrow(() -> new BatfishException("No trace with unused disposition")); updateUnpickedMaps(t); return t; }
private Trace chooseTraceByNode() { Trace t = _unpickedNodes.stream() .flatMap(node -> _nodeTraces.get(node).stream()) .filter(trace -> !_pickedTraces.contains(trace)) .findFirst() .orElseThrow(() -> new BatfishException("No trace with unused node")); updateUnpickedMaps(t); return t; }
public static Multiset<Row> diffFlowTracesToRows( Map<Flow, List<Trace>> baseFlowTraces, Map<Flow, List<Trace>> deltaFlowTraces, int maxTraces) { Multiset<Row> rows = LinkedHashMultiset.create(); checkArgument( baseFlowTraces.keySet().equals(deltaFlowTraces.keySet()), "Base and delta flow traces should have same flows"); for (Flow flow : baseFlowTraces.keySet()) { rows.add( Row.of( COL_FLOW, flow, TableDiff.baseColumnName(COL_TRACES), TracePruner.prune(baseFlowTraces.get(flow), maxTraces), TableDiff.baseColumnName(COL_TRACE_COUNT), baseFlowTraces.get(flow).size(), TableDiff.deltaColumnName(COL_TRACES), TracePruner.prune(deltaFlowTraces.get(flow), maxTraces), TableDiff.deltaColumnName(COL_TRACE_COUNT), deltaFlowTraces.get(flow).size())); } return rows; } }
@Test public void testPickFill() { // once we've covered all dispositions and flows, fill with unused traces in input order assertThat( prune( ImmutableList.of( TRACE_A_B_ACCEPTED, TRACE_A_ACCEPTED, TRACE_B_ACCEPTED, TRACE_C_ACCEPTED), 3), equalTo(ImmutableList.of(TRACE_A_B_ACCEPTED, TRACE_C_ACCEPTED, TRACE_A_ACCEPTED))); } }
@Test public void testPreferDispositionOverNode() { assertThat( prune(ImmutableList.of(TRACE_A_ACCEPTED, TRACE_B_ACCEPTED, TRACE_A_DENIED_IN), 2), equalTo(ImmutableList.of(TRACE_A_ACCEPTED, TRACE_A_DENIED_IN))); }
@Test public void testPickByNode() { assertThat( prune( ImmutableList.of( TRACE_A_B_ACCEPTED, TRACE_A_ACCEPTED, TRACE_B_ACCEPTED, TRACE_C_ACCEPTED), 2), equalTo(ImmutableList.of(TRACE_A_B_ACCEPTED, TRACE_C_ACCEPTED))); }
@Test public void testEmpty() { assertThat(prune(ImmutableList.of(), 5), empty()); }
@Test public void testPickNone() { assertThat(prune(ImmutableList.of(TRACE_A_ACCEPTED), 0), empty()); }