context: // GtkSharp.Generation.ObjectGen.cs - The Object Generatable.
  //
  // Author: Mike Kestner <mkestner@ximian.com>
  //
  // Copyright (c) 2001-2003 Mike Kestner
  // Copyright (c) 2003-2004 Novell, Inc.
  //
  // This program is free software; you can redistribute it and/or
  // modify it under the terms of version 2 of the GNU General Public
  // License as published by the Free Software Foundation.
  //
  // This program is distributed in the hope that it will be useful,
  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  // General Public License for more details.
  //
  // You should have received a copy of the GNU General Public
  // License along with this program; if not, write to the
  // Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  // Boston, MA 02111-1307, USA.
  
  
  namespace GtkSharp.Generation {
  
  	using System;
  	using System.Collections.Generic;
  	using System.IO;
  	using System.Text;
  	using System.Xml;
  
  	public class ObjectGen : ObjectBase  {
  
  		private IList<string> custom_attrs = new List<string> ();
  		private IList<XmlElement> strings = new List<XmlElement> ();
  		private IDictionary<string, ChildProperty> childprops = new Dictionary<string, ChildProperty> ();
  		private static IDictionary<string, DirectoryInfo> dirs = new Dictionary<string, DirectoryInfo> ();
  
  		public ObjectGen (XmlElement ns, XmlElement elem) : base (ns, elem, false)
  		{
  			foreach (XmlNode node in elem.ChildNodes) {
  				XmlElement member = node as XmlElement;
  				if (member == null) {
  					continue;
  				}
  
  				if (member.GetAttributeAsBoolean ("hidden"))
  					continue;
  
  				switch (node.Name) {
  				case "callback":
  					Statistics.IgnoreCount++;
  					break;
  
  				case "custom-attribute":
  					custom_attrs.Add (member.InnerXml);
  					break;
  
  				case "static-string":
  					strings.Add (member);
  					break;
  
  				case "childprop":
  					string name = member.GetAttribute ("name");
  					while (childprops.ContainsKey (name))
  						name += "mangled";
  					childprops.Add (name, new ChildProperty (member, this));
  					break;
  
  				default:
  					if (!IsNodeNameHandled (node.Name))
  						Console.WriteLine ("Unexpected node " + node.Name + " in " + CName);
  					break;
  				}
  			}
  		}
  
  		public override string CallByName (string var, bool owned)
  		{
  			return String.Format ("{0} == null ? IntPtr.Zero : {0}.{1}", var, owned ? "OwnedHandle" : "Handle");
  		}
  
  		public override bool Validate ()
  		{
  			LogWriter log = new LogWriter (QualifiedName);
  
  			var invalids = new List<string> ();
  
  			foreach (string prop_name in childprops.Keys) {
  				if (!childprops [prop_name].Validate (log))
  					invalids.Add (prop_name);
  			}
  			foreach (string prop_name in invalids)
  				childprops.Remove (prop_name);
  
  			return base.Validate ();
  		}
  
  		private bool DisableVoidCtor {
  			get {
  				return Elem.GetAttributeAsBoolean ("disable_void_ctor");
  			}
  		}
  
  		private class DirectoryInfo {
  			public string assembly_name;
  			public IDictionary<string, string> objects;
  
  			public DirectoryInfo (string assembly_name)
  			{
  				this.assembly_name = assembly_name;
  				objects = new Dictionary<string, string> ();
  			}
  		}
  
  		private static DirectoryInfo GetDirectoryInfo (string dir, string assembly_name)
  		{
  			DirectoryInfo result;
  
  			if (dirs.ContainsKey (dir)) {
  				result = dirs [dir];
  				if  (result.assembly_name != assembly_name) {
  					Console.WriteLine ("Can't put multiple assemblies in one directory.");
  					return null;
  				}
  
  				return result;
  			}
  
  			result = new DirectoryInfo (assembly_name);
  			dirs.Add (dir, result);
  			
  			return result;
  		}
  
  		public override void Generate (GenerationInfo gen_info)
  		{
  			gen_info.CurrentType = QualifiedName;
  
  			string asm_name = gen_info.AssemblyName.Length == 0 ? NS.ToLower () + "-sharp" : gen_info.AssemblyName;
  			DirectoryInfo di = GetDirectoryInfo (gen_info.Dir, asm_name);
  
  			StreamWriter sw = gen_info.Writer = gen_info.OpenStream (Name, NS);
  
  			sw.WriteLine ("namespace " + NS + " {");
  			sw.WriteLine ();
  			sw.WriteLine ("\tusing System;");
  			sw.WriteLine ("\tusing System.Collections;");
  			sw.WriteLine ("\tusing System.Collections.Generic;");
  			sw.WriteLine ("\tusing System.Runtime.InteropServices;");
  			sw.WriteLine ();
  
  			SymbolTable table = SymbolTable.Table;
  
  			sw.WriteLine ("#region Autogenerated code");
  			if (IsDeprecated)
  				sw.WriteLine ("\t[Obsolete]");
  			foreach (string attr in custom_attrs)
  				sw.WriteLine ("\t" + attr);
  			sw.Write ("\t{0} {1}partial class " + Name, IsInternal ? "internal" : "public", IsAbstract ? "abstract " : "");
  			string cs_parent = table.GetCSType(Elem.GetAttribute("parent"));
  			if (cs_parent != "") {
  				di.objects.Add (CName, QualifiedName);
  				sw.Write (" : " + cs_parent);
  			}
  			foreach (string iface in interfaces) {
  				if (Parent != null && Parent.Implements (iface))
  					continue;
  				sw.Write (", " + table.GetCSType (iface));
  			}
  			foreach (string iface in managed_interfaces) {
  				if (Parent != null && Parent.Implements (iface))
  					continue;
  				sw.Write (", " + iface);
  			}
  			sw.WriteLine (" {");
  			sw.WriteLine ();
  
  			GenCtors (gen_info);
  			GenProperties (gen_info, null);
  			GenFields (gen_info);
  			GenChildProperties (gen_info);
  			
  			bool has_sigs = (sigs != null && sigs.Count > 0);
  			if (!has_sigs) {
  				foreach (string iface in interfaces) {
  					InterfaceGen igen = table.GetClassGen (iface) as InterfaceGen;
  					if (igen != null && igen.Signals != null) {
  						has_sigs = true;
  						break;
  					}
  				}
  			}
  
  			if (has_sigs && Elem.HasAttribute("parent")) {
  				GenSignals (gen_info, null);
  			}
  
  			GenConstants (gen_info);
  			GenClassMembers (gen_info, cs_parent);
  			GenMethods (gen_info, null, null);
  
  			if (interfaces.Count != 0) {
  				var all_methods = new Dictionary<string, Method> ();
  				foreach (Method m in Methods.Values) {
  					all_methods[m.Name] = m;
  				}
  				var collisions = new Dictionary<string, bool> ();
  				foreach (string iface in interfaces) {
  
gt: 					ClassBase igen = table.GetClassGen (iface);