import java.io.IOException;
import java.io.Writer;
import java.util.LinkedList;
import java.util.List;


public class B<A> {
	A element;
	List<B<A>> kinder;
	public B(A element, List<B<A>> kinder) {
		super();
		this.element = element;
		this.kinder = kinder;
	}

	int count(){
		int result=0;
		for (B<A> kid:kinder){
			result=result+kid.count();
		}
		return result+1;
	}
	
	public boolean contains(A a){
		if (element.equals(a)) return true;
		for (B<A> child:kinder){
			if (child.contains(a)) return true;
		}
		return false;
	}
	void postOrder(List<A> result){
		for (B<A> child:kinder){
			child.postOrder(result);
		}
		result.add(element);
	}
	void preOrder(List<A> result){
		for (B<A> child:kinder){
			child.preOrder(result);
		}
		result.add(element);
	}
	
	int maxDepth(){
		int result = 0;
		for (B<A> child:kinder){
			result=Math.max(child.maxDepth(),result);
		}
		return result+1;
	}

	<R>  B<R> map(Function<A,R> f){
		List<B<R>> newKids = new LinkedList<B<R>>();
		for (B<A> kid:kinder){
			newKids.add(kid.map(f));
		}
		return new B<R>(f.apply(element),newKids);
	}
	
	void writeAsXML(Writer schreiber) throws IOException{
		schreiber.write("<knoten>");
		schreiber.write("<element>");
		schreiber.write(""+element);
		schreiber.write("</element>");
		schreiber.write("<kinder>");
		for (B<A> kid:kinder){kid.writeAsXML(schreiber);}
		schreiber.write("</kinder>");
		schreiber.write("</knoten>");
	}
	@Override
	public String toString() {
		String result = element.toString()+"[";
		for (B<A> kid:kinder){
			result=result+" "+kid.toString();
		}

		// TODO Auto-generated method stub
		return result+"]";
	}
	
	public static void main(String[] args) {
		B<String> g
		= new B<String>("g",new LinkedList< B<String>>());
		B<String> h
		= new B<String>("h",new LinkedList< B<String>>());
		B<String> i
		= new B<String>("ii",new LinkedList< B<String>>());
		List<B<String>> fkids = new LinkedList< B<String>>();
		fkids.add(g);fkids.add(h);fkids.add(i);
		B<String> f
		= new B<String>("fkl",fkids);
		B<String> fff=
		f.map(new Function<String, String>(){
			@Override
			public String apply(String arg) {
				return arg+arg+arg;
			}
		});
		B<Integer> f3 =
			fff.map(new Function<String, Integer>(){
				@Override
				public Integer apply(String arg) {
					return arg.length();
				}
			});		
		System.out.println(f);
		System.out.println(fff);
		System.out.println(f3);
	
	}
	
}
