/*
* Copyright 2013 Square Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.mortar.util;
import com.zhuinden.servicetree.ServiceTree;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class NodePrinter {
private NodePrinter() {
}
public static String scopeHierarchyToString(ServiceTree.Node mortarScope) {
StringBuilder result = new StringBuilder("Scope Hierarchy:\n");
ServiceTree.Node rootScope = getRootScope(mortarScope);
Node rootNode = new PrintNode(rootScope);
nodeHierarchyToString(result, 0, 0, rootNode);
return result.toString();
}
interface Node {
String getName();
List<Node> getChildNodes();
}
private static class PrintNode
implements Node {
private final ServiceTree.Node mortarScope;
PrintNode(ServiceTree.Node mortarScope) {
this.mortarScope = mortarScope;
}
@Override
public String getName() {
return "SCOPE " + mortarScope.getKey().toString();
}
@Override
public List<Node> getChildNodes() {
List<Node> childNodes = new ArrayList<>();
addScopeChildren(childNodes);
return childNodes;
}
private void addScopeChildren(List<Node> childNodes) {
for(ServiceTree.Node childScope : mortarScope.getChildren()) {
childNodes.add(new PrintNode(childScope));
}
}
}
private static ServiceTree.Node getRootScope(ServiceTree.Node scope) {
while(scope.getParent() != null) {
scope = scope.getParent();
}
return scope;
}
private static void nodeHierarchyToString(StringBuilder result, int depth, long lastChildMask, Node node) {
appendLinePrefix(result, depth, lastChildMask);
result.append(node.getName()).append('\n');
List<Node> childNodes = node.getChildNodes();
Collections.sort(childNodes, new NodeSorter());
int lastIndex = childNodes.size() - 1;
int index = 0;
for(Node childNode : childNodes) {
if(index == lastIndex) {
lastChildMask = lastChildMask | (1 << depth);
}
nodeHierarchyToString(result, depth + 1, lastChildMask, childNode);
index++;
}
}
private static void appendLinePrefix(StringBuilder result, int depth, long lastChildMask) {
int lastDepth = depth - 1;
// Add a non-breaking space at the beginning of the line because Logcat eats normal spaces.
result.append('\u00a0');
for(int parentDepth = 0; parentDepth <= lastDepth; parentDepth++) {
if(parentDepth > 0) {
result.append(' ');
}
boolean lastChild = (lastChildMask & (1 << parentDepth)) != 0;
if(lastChild) {
if(parentDepth == lastDepth) {
result.append('`');
} else {
result.append(' ');
}
} else {
if(parentDepth == lastDepth) {
result.append('+');
} else {
result.append('|');
}
}
}
if(depth > 0) {
result.append("-");
}
}
private static class NodeSorter
implements Comparator<Node> {
@Override
public int compare(Node lhs, Node rhs) {
return lhs.getName().compareTo(rhs.getName());
}
}
}