public interface IDoc : Object {

	public abstract string generate ();
	public abstract Object copy ();
}

public abstract class AbstractDocList : Gee.ArrayList<IDoc>, IDoc {

	protected abstract AbstractDocList create_default_instance ();

	protected AbstractDocList list_copy () {
		stdout.printf ("AbstractDocList::list_copy ()\n");
		stdout.printf ("this.get_type ().name () = %s\n", this.get_type ().name ());
		//var clone = Object.new (this.get_type ()) as AbstractDocList;
		var clone = create_default_instance ();

		foreach (IDoc dociface in this)
			clone.add (dociface.copy () as IDoc);

		return clone;
	}

	public Object copy () {
		stdout.printf ("AbstractDocList::copy ()\n");
		return list_copy ();
	}

	public string generate () {
		stdout.printf ("AbstractDocList::generate ()\n");
		var result = new StringBuilder ();

		foreach (IDoc dociface in this)
			result.append (dociface.generate ());

		return result.str;
	}
}

public class Text : Object, IDoc {

	public string text = "";

	public Text (string text) {
		this.text = text;
	}

	public Object copy () {
		stdout.printf ("Text::copy ()\n");
		return new Text (text);
	}

	public string generate () {
		stdout.printf ("Text::generate ()\n");
		return text;
	}
}

public class Glob : AbstractDocList {
	protected override AbstractDocList create_default_instance () { return new Glob (); }
}

IDoc CreateObject () {
	var glob = new Glob ();
	for (var i = 0; i < 5; ++i) {
		glob.add (new Text (i.to_string ()));
	}
	return glob;
}

void main () {
	//stdout.printf ("Hello world!\n");
	var idoc = CreateObject ();
	stdout.printf ("idoc.generate () = %s\n", (idoc.copy () as IDoc).generate ());
}
