MODULE SqlObxGen;
(**
	project	= "BlackBox"
	organization	= "www.oberon.ch"
	contributors	= "Oberon microsystems"
	version	= "System/Rsrc/About"
	copyright	= "System/Rsrc/About"
	license	= "Docu/BB-License"
	changes	= "
	- YYYYMMDD, nn, ...
	"
	issues	= "
	- ...
	"

**)

	IMPORT Views, SqlDB, SqlObxDB, SqlObxNets, SqlObxViews;

	CONST
		protocol = "SqlOdbc";
		id = ""; password = "";
		datasource = "Test Database";

	TYPE
		Node = POINTER TO RECORD
			next: Node;
			id: INTEGER
		END;

	VAR
		company*: RECORD
			id*: INTEGER;
			name*: ARRAY 32 OF CHAR
		END;

		ownership*: RECORD
			owner*, owned*: INTEGER;
			percent*: INTEGER
		END;

	VAR
		set, queue: Node;
		g: SqlObxNets.Net;

	PROCEDURE Marked (id: INTEGER): BOOLEAN;
		VAR h: Node;
	BEGIN	(* test whether id is in set *)
		h := set; WHILE (h # NIL) & (h.id # id) DO h := h.next END;
		RETURN h # NIL
	END Marked;

	PROCEDURE Mark (id: INTEGER);
		VAR h: Node;
	BEGIN	(* include id in set (not idempotent) *)
		NEW(h); h.id := id; h.next := set; set := h
	END Mark;

	PROCEDURE Enqueue (id: INTEGER);
		VAR h: Node;
	BEGIN	(* insert id at end of queue (idempotent) *)
		IF queue = NIL THEN
			NEW(queue); h := queue
		ELSE
			h := queue; WHILE (h.next # NIL) & (h.id # id) DO h := h.next END;
			IF h.id # id THEN NEW(h.next); h := h.next END
		END;
		h.id := id
	END Enqueue;

	PROCEDURE Dequeue (VAR id: INTEGER);
	BEGIN	(* remove first queue element *)
		IF queue # NIL THEN
			id := queue.id; queue := queue.next
		ELSE
			id := 0
		END
	END Dequeue;

	PROCEDURE ProcessCompany (t: SqlDB.Table; p: ANYPTR);
		VAR h: SqlObxNets.Net; cp: SqlObxNets.Company;
	BEGIN	(* process all companies in set with id > 0 *)
		ASSERT(t.rows = 1, 20);
		t.Read(0, company);
		SqlObxNets.AddCompany(g, company.id, company.name, "", 0);
		WHILE (set # NIL) & (set.id < 0) DO set := set.next END;
		IF set # NIL THEN
			SqlObxDB.searchId := set.id; ASSERT(set.id > 0, 100); set := set.next;
			t.Exec("SELECT id, name FROM Companies WHERE id = :SqlObxDB.searchId");
			t.Call(ProcessCompany, NIL)
		ELSE
			cp := SqlObxNets.ThisCompany(g, company.id); h := g; g := NIL; Views.OpenView(SqlObxViews.New(h, cp))
		END
	END ProcessCompany;

	PROCEDURE ^ConsumeCompany(t: SqlDB.Table; p: ANYPTR);

	PROCEDURE ProduceCompanies (t: SqlDB.Table; p: ANYPTR);
		VAR i: INTEGER;
	BEGIN
		i := 0;
		WHILE i < t.rows DO
			t.Read(i, ownership);
			SqlObxNets.AddOwnership(g, ownership.owner, ownership.owned, ownership.percent);
			Enqueue(ownership.owner); Enqueue(-ownership.owner);
			Enqueue(ownership.owned); Enqueue(-ownership.owned);
			INC(i)
		END;
		t.Call(ConsumeCompany, NIL)
	END ProduceCompanies;

	PROCEDURE ConsumeCompany (t: SqlDB.Table; p: ANYPTR);
		VAR id: INTEGER;
	BEGIN
		Dequeue(id); WHILE (id # 0) & Marked(id) DO Dequeue(id) END;
		IF id # 0 THEN	(* ~Marked(id) *)
			Mark(id);
			IF id > 0 THEN	(* select owner *)
				SqlObxDB.searchId := id;
				t.Exec("SELECT * FROM Ownership WHERE owned = :SqlObxDB.searchId");
			ELSE	(* select owned *)
				SqlObxDB.searchId := -id;
				t.Exec("SELECT * FROM Ownership WHERE owner = :SqlObxDB.searchId")
			END;
			t.Call(ProduceCompanies, NIL)
		ELSE	(* queue is empty *)
			ASSERT(queue = NIL, 100);
			WHILE (set # NIL) & (set.id < 0) DO set := set.next END; ASSERT(set # NIL, 101); ASSERT(set.id > 0, 102);
			SqlObxDB.searchId := set.id; set := set.next;
			t.Exec("SELECT id, name FROM Companies WHERE id = :SqlObxDB.searchId");
			t.Call(ProcessCompany, NIL)
		END
	END ConsumeCompany;

	PROCEDURE GenNet*;
		VAR d: SqlDB.Database; res: INTEGER; t: SqlDB.Table;
	BEGIN
		ASSERT(SqlObxDB.searchId > 0, 20);
		SqlDB.OpenDatabase(protocol, id, password, datasource, SqlDB.async, SqlDB.hideErrors, d, res);
		ASSERT(d # NIL, 100);
		t := d.NewTable();
		set := NIL; queue := NIL; g := SqlObxNets.New();
		company.id := SqlObxDB.searchId;
		Enqueue(company.id); Enqueue(-company.id);	(* produce first company *)
		t.Call(ConsumeCompany, NIL);
		t.Clear
	END GenNet;

END SqlObxGen.
