import java.io.File;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Vector;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.Vector;
import java.util.Map.Entry;

public class Main {

	public static void main(String[] args) {

		String dirname = "/home/pix/k";

		LinkedList<String> stack = new LinkedList<String>();
		stack.add(dirname);

		LinkedList<TreeAssociation> nodestack = new LinkedList<TreeAssociation>();
		TreeAssociation root = new TreeAssociation(dirname);
		nodestack.add(root);
		
		while(!stack.isEmpty())
		{
			String s = stack.pop();
			TreeAssociation n = nodestack.pop();
			File dir = new File(s);
			String [] files = dir.list();
			
			if(files != null)
			{
				for(String _s : files)
				{
					stack.add(s + "/" + _s);
					TreeAssociation _n = new TreeAssociation(_s);
					n.addAssociation(_n);
					nodestack.add(_n);
				}
			}
		}
		root.prefixPrint("", true);
	}
}

class TreeAssociation implements Comparable<TreeAssociation>
{
	String name;
	
	HashMap<String, Vector<TreeAssociation> > groups;
	private static String DEFAULT_GROUP_NAME = "__default_assoc"; 
	
	public TreeAssociation(String name)
	{
		this.name = name;
		groups = new HashMap<String, Vector<TreeAssociation> >();
	}
	
	
	public void addAssociation(TreeAssociation a)
	{
		addAssociation(DEFAULT_GROUP_NAME, a);
	}

	public void addAssociation(String groupname, TreeAssociation a)
	{
		if(!groups.containsKey(groupname))
			groups.put(groupname, new Vector<TreeAssociation>());
		
		Vector<TreeAssociation> list = groups.get(groupname);
		list.add(a);
	}
	
	public Vector<TreeAssociation> getAssociationGroup(String name)
	{
		return groups.get(name);
	}
	
	public void prefixPrint(String prefix, boolean terminal, String Qualifier)
	{
		String str = prefix + (terminal ? "`- " : "+- ") + toString();
		System.out.println(str);
		
		Set<Entry<String, Vector<TreeAssociation>>> candidates = getQualifyingGroups(Qualifier);
		
		String [] tokens = Qualifier.split(":", 2);
		String strippedQualifier = null; 
			
		if(tokens.length == 1)
		{
			strippedQualifier = "*";
		}
		else
			strippedQualifier = tokens[1];
			
		
		String newPrefix = terminal ? prefix + "   ": prefix + "|  "; 
		// go thru all the groups and print them 
		int numGroups = candidates.size();
		int count = 0;
		for(Entry<String, Vector<TreeAssociation>> entry : candidates)
		{
			boolean isDefaultGroup = entry.getKey().equals(DEFAULT_GROUP_NAME);
			
			String groupPrefix = null;
			if(count++ == numGroups - 1)
			{
				if(!isDefaultGroup)
					System.out.println(newPrefix + "`- " + entry.getKey());
				groupPrefix = newPrefix + (isDefaultGroup ? "":"   ");
			}
			else
			{
				if(!isDefaultGroup)
					System.out.println(newPrefix + "+- " + entry.getKey());
				groupPrefix = newPrefix + (isDefaultGroup ? "":"|  ");
			}
			
			Vector<TreeAssociation> v = entry.getValue();
			TreeAssociation [] _v = v.toArray(new TreeAssociation[0]);
			Arrays.sort(_v);
			for(int k = 0; k < _v.length - 1; k++)
			{
				_v[k].prefixPrint(groupPrefix, false, strippedQualifier);
			}
			_v[(_v.length - 1)].prefixPrint(groupPrefix, true, strippedQualifier);
		}
	}
	
	public Set<Entry<String, Vector<TreeAssociation>>> getQualifyingGroups(String Qualifier)
	{
		String [] tokens = Qualifier.split(":", 2);
		String valid = null;
		
		if(tokens.length == 1)
		{
			return groups.entrySet();
		}
		else
			valid = tokens[0];
		
		HashSet<Entry<String, Vector<TreeAssociation>>> p = new HashSet<Entry<String, Vector<TreeAssociation>>>();
		for(Entry<String, Vector<TreeAssociation>> e : groups.entrySet())
		{
			if (e.getKey().equals(valid))
			{
				p.add(e);
			}
		}
		return p;
	}

	public void prefixPrint(String prefix, boolean terminal)
	{
		prefixPrint(prefix, terminal, "*");
	}
	
	public String toString()
	{
		return name;
	}

	@Override
	public int compareTo(TreeAssociation o) {
		
		return name.compareTo(o.name);
	}
}
