public String toGraphviz() { StringBuilder builder = new StringBuilder(); builder.append("digraph QuantileDigest {\n").append("\tgraph [ordering=\"out\"];"); final List<Node> nodes = new ArrayList<>(); postOrderTraversal( root, new Callback() { @Override public boolean process(Node node) { nodes.add(node); return true; } }); Multimap<Integer, Node> nodesByLevel = Multimaps.index( nodes, new Function<Node, Integer>() { @Override public Integer apply(Node input) { return input.level; } }); for (Map.Entry<Integer, Collection<Node>> entry : nodesByLevel.asMap().entrySet()) { builder.append("\tsubgraph level_" + entry.getKey() + " {\n").append("\t\trank = same;\n"); for (Node node : entry.getValue()) { builder.append( String.format( "\t\t%s [label=\"[%s..%s]@%s\\n%s\", shape=rect, style=filled,color=%s];\n", idFor(node), node.getLowerBound(), node.getUpperBound(), node.level, node.weightedCount, node.weightedCount > 0 ? "salmon2" : "white")); } builder.append("\t}\n"); } for (Node node : nodes) { if (node.left != null) { builder.append(format("\t%s -> %s;\n", idFor(node), idFor(node.left))); } if (node.right != null) { builder.append(format("\t%s -> %s;\n", idFor(node), idFor(node.right))); } } builder.append("}\n"); return builder.toString(); }
public OptiqSchema(OptiqSchema parent, final Schema schema, String name) { this.parent = parent; this.schema = schema; this.name = name; assert (parent == null) == (this instanceof OptiqRootSchema); //noinspection unchecked this.compositeTableMap = CompositeMap.of( Maps.transformValues( tableMap, new com.google.common.base.Function<TableEntry, Table>() { public Table apply(TableEntry input) { return input.getTable(); } }), Maps.transformValues( Multimaps.filterEntries( functionMap, new Predicate<Map.Entry<String, FunctionEntry>>() { public boolean apply(Map.Entry<String, FunctionEntry> entry) { final Function function = entry.getValue().getFunction(); return function instanceof TableMacro && function.getParameters().isEmpty(); } }) .asMap(), new com.google.common.base.Function<Collection<FunctionEntry>, Table>() { public Table apply(Collection<FunctionEntry> input) { // At most one function with zero parameters. final TableMacro tableMacro = (TableMacro) input.iterator().next().getFunction(); return tableMacro.apply(ImmutableList.of()); } }), Compatible.INSTANCE.asMap( schema.getTableNames(), new com.google.common.base.Function<String, Table>() { public Table apply(String input) { return schema.getTable(input); } })); // TODO: include schema's functions in this map. this.compositeFunctionMap = Multimaps.transformValues( functionMap, new com.google.common.base.Function<FunctionEntry, Function>() { public Function apply(FunctionEntry input) { return input.getFunction(); } }); //noinspection unchecked this.compositeSubSchemaMap = CompositeMap.of( subSchemaMap, Compatible.INSTANCE.asMap( schema.getSubSchemaNames(), new com.google.common.base.Function<String, OptiqSchema>() { public OptiqSchema apply(String name) { return add(name, schema.getSubSchema(name)); } })); }