namespace GConf.Tools { using GConf; using System; using System.Xml; using System.Collections; using System.IO; using System.Text; class SchemaGen { private Hashtable keys = new Hashtable (); private Hashtable classes = new Hashtable (); static void Die (string error) { Console.WriteLine (error); Environment.Exit (1); } void DieInvalid (string filename) { Die (filename + " is an invalid schema"); } void Parse (string filename) { XmlDocument doc = new XmlDocument (); try { Stream stream = File.OpenRead (filename); doc.Load (stream); stream.Close (); } catch (XmlException e) { Die ("Could not parse " + filename); } XmlElement root = doc.DocumentElement; if (!(root != null && root.HasChildNodes && root.Name == "gconfschemafile")) DieInvalid (filename); foreach (XmlNode slist in root.ChildNodes) { if (!(slist != null && slist.Name == "schemalist")) continue; foreach (XmlNode schema_node in slist.ChildNodes) { XmlElement schema = schema_node as XmlElement; if (!(schema != null && schema.Name == "schema")) continue; XmlElement key = schema["applyto"]; XmlElement type = schema["cstype"]; if (type == null) type = schema["type"]; if (key == null || type == null) DieInvalid (filename); keys.Add (key.InnerText, type.InnerText); if (type.HasAttribute ("class")) classes.Add (key.InnerText, type.GetAttribute ("class")); } } } string ExtractPrefix () { string path = null; foreach (string key in keys.Keys) { int slash = key.LastIndexOf ('/'); if (slash < 0) continue; string new_path = key.Substring (0, slash + 1); if (path == null || new_path.Length < path.Length) path = new_path; } return path; } string BaseName (string key) { int slash = key.LastIndexOf ('/'); if (slash < 0) return key; return key.Substring (slash + 1); } string PropertyName (string key) { string basename = BaseName (key); StringBuilder sb = new StringBuilder (); bool needs_caps = true; foreach (char orig in basename) { char c = orig; if (c == '_' || c == '-') { needs_caps = true; continue; } if (needs_caps) { c = c.ToString ().ToUpper ()[0]; needs_caps = false; } sb.Append (c); } return sb.ToString (); } string CSType (string key, string type) { switch (type) { case "float": return "double"; case "string": return "string"; case "int": return "int"; case "bool": return "bool"; case "color": return "System.Drawing.Color"; case "enum": if (classes.Contains (key)) return (string) classes[key]; else return "string"; case "list": return "System.Array"; default: return null; } } void GenerateSimpleProperty (TextWriter sw, string key, string key_str, string type, string cstype) { sw.WriteLine ("\t\t\tget {"); sw.WriteLine ("\t\t\t\treturn ({0}) client.Get ({1});", cstype, key_str); sw.WriteLine ("\t\t\t}"); sw.WriteLine ("\t\t\tset {"); sw.WriteLine ("\t\t\t\tclient.Set ({0}, value);", key_str); sw.WriteLine ("\t\t\t}"); } void GenerateColorProperty (TextWriter sw, string key, string key_str, string type, string cstype) { sw.WriteLine ("\t\t\tget {"); sw.WriteLine ("\t\t\t\treturn System.Drawing.ColorTranslator.FromHtml ((string) client.Get ({0}));", key_str); sw.WriteLine ("\t\t\t}"); sw.WriteLine ("\t\t\tset {"); sw.WriteLine ("\t\t\t\tclient.Set ({0}, System.Drawing.ColorTranslator.ToHtml (value));", key_str); sw.WriteLine ("\t\t\t}"); } void GenerateEnumProperty (TextWriter sw, string key, string key_str, string type, string cstype) { sw.WriteLine ("\t\t\tget {"); sw.WriteLine ("\t\t\t\ttry {"); sw.WriteLine ("\t\t\t\t\treturn ({0}) System.Enum.Parse (typeof ({0}), (string) client.Get ({1}));", cstype, key_str); sw.WriteLine ("\t\t\t\t} catch (System.Exception e) {"); sw.WriteLine ("\t\t\t\t\treturn ({0}) 0;", cstype); sw.WriteLine ("\t\t\t\t}"); sw.WriteLine ("\t\t\t}"); sw.WriteLine ("\t\t\tset {"); sw.WriteLine ("\t\t\t\tclient.Set ({0}, System.Enum.GetName (typeof ({1}), value));", key_str, cstype); sw.WriteLine ("\t\t\t}"); } void GenerateEvent (TextWriter sw, string name, string key_str) { sw.WriteLine (); sw.WriteLine ("\t\tpublic static event GConf.NotifyEventHandler {0}Changed", name); sw.WriteLine ("\t\t{"); sw.WriteLine ("\t\t\tadd {"); sw.WriteLine ("\t\t\t\tclient.AddNotify ({0}, value);", key_str); sw.WriteLine ("\t\t\t}"); sw.WriteLine ("\t\t\tremove{"); sw.WriteLine ("\t\t\t\tclient.RemoveNotify ({0}, value);", key_str); sw.WriteLine ("\t\t\t}"); sw.WriteLine ("\t\t}"); } void Generate (string ns_str) { string path = ExtractPrefix (); TextWriter sw = Console.Out; sw.WriteLine ("namespace {0}", ns_str); sw.WriteLine ("{"); sw.WriteLine ("\tpublic class Settings"); sw.WriteLine ("\t{"); sw.WriteLine ("\t\tstatic GConf.Client client = new GConf.Client ();"); GenerateEvent (sw, "", "\"" + path.Substring (0, path.Length - 1) + "\""); foreach (string key in keys.Keys) { string type = (string) keys[key]; string cstype = CSType (key, type); string key_str = "\"" + key + "\""; if (cstype == null) { Console.Error.WriteLine ("Warning: unknown type \"{0}\" for key {1}", type, key); continue; } sw.WriteLine (); sw.WriteLine ("\t\tpublic static {0} {1}", cstype, PropertyName (key)); sw.WriteLine ("\t\t{"); switch (type) { case "color": GenerateColorProperty (sw, key, key_str, type, cstype); break; case "enum": GenerateEnumProperty (sw, key, key_str, type, cstype); break; default: GenerateSimpleProperty (sw, key, key_str, type, cstype); break; } sw.WriteLine ("\t\t}"); GenerateEvent (sw, PropertyName (key), key_str); } sw.WriteLine ("\t}"); sw.WriteLine (); sw.WriteLine ("\tpublic class SettingKeys"); sw.WriteLine ("\t{"); foreach (string key in keys.Keys) { sw.WriteLine ("\t\tpublic static string {0}", PropertyName (key)); sw.WriteLine ("\t\t{"); sw.WriteLine ("\t\t\tget {"); sw.WriteLine ("\t\t\t\t return \"{0}\";", key); sw.WriteLine ("\t\t\t}"); sw.WriteLine ("\t\t}"); } sw.WriteLine ("\t}"); sw.WriteLine ("}"); } public static void Main (string[] args) { if (args.Length < 2) Die ("Usage: gconfsharp-schemagen namespace schemafile"); string ns = args[0]; string filename = args[1]; SchemaGen gen = new SchemaGen (); gen.Parse (filename); gen.Generate (ns); } } }