5 using System
.Text
.RegularExpressions
;
6 using System
.Collections
.Generic
;
7 using System
.Reflection
;
9 public class GSettingsSchemaExtractorProgram
11 private static HashSet
<FieldInfo
> schema_fields
;
12 private static int schema_count
;
14 public static void Main(string [] args
)
16 if (args
.Length
!= 1) {
17 Console
.Error
.WriteLine ("Usage: gsettings-schema-extractor.exe /path/to/binaries/");
21 var dir
= new DirectoryInfo (args
[0]);
23 Console
.Error
.WriteLine (args
[0] + " does not exist");
30 private static void Extract (DirectoryInfo dir
)
32 var dot_net_assemblies
= dir
.EnumerateFiles ()
33 .Where (f
=> f
.FullName
.EndsWith (".dll", true, System
.Globalization
.CultureInfo
.InvariantCulture
) ||
34 f
.FullName
.EndsWith (".exe", true, System
.Globalization
.CultureInfo
.InvariantCulture
));
36 if (!dot_net_assemblies
.Any ()) {
37 Console
.Error
.WriteLine ("No binary files found in specified path");
41 var types
= new List
<Type
> ();
42 foreach (var file
in dot_net_assemblies
) {
43 Assembly asm
= Assembly
.LoadFrom (file
.FullName
);
44 types
.AddRange (asm
.GetTypes ());
45 Console
.WriteLine ("Inspecting types in " + file
.Name
);
48 StringBuilder sbuilder
= Extract (types
);
49 if (sbuilder
!= null) {
51 string outputFile
= Path
.Combine (dir
.FullName
, "org.gnome.banshee.gschema.xml");
53 using (StreamWriter writer
= new StreamWriter (outputFile
)) {
54 writer
.Write (sbuilder
.ToString ());
57 Console
.WriteLine ("Successfully wrote " + Path
.GetFileName (outputFile
));
61 internal static StringBuilder
Extract (IEnumerable
<Type
> types
)
63 Console
.WriteLine ("Generating schemas");
65 schema_fields
= new HashSet
<FieldInfo
> ();
67 foreach (Type type
in types
) {
68 foreach (FieldInfo field
in type
.GetFields (BindingFlags
.Public
|
69 BindingFlags
.NonPublic
|
70 BindingFlags
.Static
)) {
71 if (CheckForValidEntry (type
, field
)) {
72 schema_fields
.Add (field
);
77 if (schema_fields
.Count
> 0) {
79 var schemaSet
= new SchemaSet ();
81 foreach (FieldInfo field
in schema_fields
) {
82 GSettingsKey
.ExtractFromField (schemaSet
, field
);
85 StringBuilder final
= new StringBuilder ();
86 final
.Append ("<schemalist>\n");
88 foreach (GSettingsSchema schema
in schemaSet
.Schemas
.Values
) {
89 final
.Append (schema
.ToString ());
92 final
.Append ("</schemalist>\n");
99 internal class InvalidSchemaException
: Exception
101 internal InvalidSchemaException (string msg
) : base (msg
)
106 static bool CheckForValidEntry (Type type
, FieldInfo field
)
108 if (!field
.FieldType
.IsGenericType
|| field
.Name
== "Zero") {
112 string type_definition
= field
.FieldType
.GetGenericTypeDefinition ().Name
;
114 if (type_definition
.StartsWith ("SchemaEntry")) {
115 Console
.WriteLine ("Found SchemaEntry: " + type
.FullName
+ "." + field
.Name
);
123 private static string GetStringValueOfFieldNamed (object schemaEntryObject
, string fieldName
)
125 FieldInfo field
= schemaEntryObject
.GetType ().GetField (fieldName
);
126 return (string)field
.GetValue (schemaEntryObject
);
129 private static string GetValueString (Type type
, object o
)
131 if (type
== typeof (bool)) {
132 return o
== null ? null : o
.ToString ().ToLower ();
135 if (type
== typeof (string)) {
136 string value = o
== null ? String
.Empty
: o
.ToString ();
137 return String
.Format ("'{0}'", value);
140 if (type
== typeof (int) || type
== typeof (double)) {
141 return o
== null ? null : o
.ToString ();
144 throw new Exception (String
.Format ("Unsupported type '{0}'", type
));
147 private static string GetGcType (Type type
)
150 throw new ArgumentNullException ("type");
153 // gctypes to return taken from http://developer.gnome.org/glib/unstable/glib-GVariant.html#GVariantClass
155 if (type
== typeof (bool)) {
159 if (type
== typeof (int)) {
163 if (type
== typeof (double)) {
167 if (type
== typeof (string)) {
171 throw new Exception (String
.Format ("Unsupported type '{0}'", type
));
174 internal struct GSettingsSchema
176 internal string Id { get; private set; }
177 internal string Path { get { return Id.Replace ("org.gnome.", "/apps/").Replace (".", "/") + "/"; }
}
179 internal HashSet
<GSettingsKey
> Keys { get; private set; }
181 internal GSettingsSchema (string id
) : this ()
184 Keys
= new HashSet
<GSettingsKey
> ();
187 public override string ToString ()
189 string result
= String
.Empty
;
190 result
+= String
.Format (" <schema id=\"{0}\" path=\"{1}\" gettext-domain=\"banshee\">\n", Id
, Path
);
191 foreach (var key
in Keys
) {
192 result
+= key
.ToString ();
194 result
+= (" </schema>\n");
200 internal struct GSettingsKey
202 internal GSettingsSchema ParentSchema { get; private set; }
203 internal string Default { get; private set; }
204 internal string KeyName { get; private set; }
205 internal string KeyType { get; private set; }
206 internal string Summary { get; private set; }
207 internal string Description { get; private set; }
209 internal static GSettingsKey
ExtractFromField (SchemaSet schemaSet
, FieldInfo field
)
212 throw new ArgumentNullException ("field");
215 object schema
= field
.GetValue (null);
216 if (schema
== null) {
217 throw new InvalidSchemaException (String
.Format (
218 "Schema could not be retrieved from field {0} in type {1}",
219 field
.Name
, field
.DeclaringType
.FullName
));
222 var default_value_field
= schema
.GetType ().GetField ("DefaultValue");
223 var default_value
= default_value_field
.GetValue (schema
);
225 var default_value_type
= default_value_field
.FieldType
;
226 var namespce
= GetStringValueOfFieldNamed (schema
, "Namespace");
227 var key
= GetStringValueOfFieldNamed (schema
, "Key");
228 var short_description
= GetStringValueOfFieldNamed (schema
, "ShortDescription");
229 var long_description
= GetStringValueOfFieldNamed (schema
, "LongDescription");
231 return new GSettingsKey (schemaSet
, default_value
, default_value_type
, namespce
, key
, short_description
, long_description
);
234 private GSettingsKey (SchemaSet schemaSet
, object defaultValue
, Type defaultValueType
,
235 string namespce
, string key
,
236 string short_desc
, string long_desc
) : this ()
238 ParentSchema
= schemaSet
.RetrieveOrCreate (namespce
);
240 Default
= GetDefault (defaultValue
, defaultValueType
);
241 KeyName
= key
.Replace ("_", "-");
242 KeyType
= GetTypeAttrib (defaultValue
, defaultValueType
);
243 Summary
= short_desc
;
244 Description
= long_desc
;
246 ParentSchema
.Keys
.Add (this);
249 public override string ToString ()
251 string result
= String
.Empty
;
252 result
+= String
.Format (" <key name=\"{0}\" type=\"{1}\">\n", KeyName
, KeyType
);
253 result
+= String
.Format (" <default>{0}</default>\n", Default
);
254 result
+= String
.Format (" <summary>{0}</summary>\n", Summary
);
255 result
+= String
.Format (" <description>{0}</description>\n", Description
);
256 result
+= (" </key>\n");
261 internal class SchemaSet
263 internal SchemaSet ()
265 Schemas
= new Dictionary
<string, GSettingsSchema
> ();
268 internal Dictionary
<string, GSettingsSchema
> Schemas { get; private set; }
270 private static string NamespaceToId (string namespce
)
272 return "org.gnome.banshee." + CamelCaseToUnderScoreLowerCase (namespce
);
275 internal GSettingsSchema
RetrieveOrCreate (string namespce
)
277 string id
= NamespaceToId (namespce
);
278 GSettingsSchema schema
;
279 if (!Schemas
.TryGetValue (id
, out schema
)) {
280 schema
= new GSettingsSchema (id
);
281 Schemas
[id
] = schema
;
287 internal static string GetTypeAttrib (object defaultValue
, Type defaultValueType
)
289 var i_enumerable_interface
= defaultValueType
.GetInterfaces ()
290 .Where (i
=> i
.IsGenericType
&& i
.GetGenericTypeDefinition () == typeof (IEnumerable
<>)).FirstOrDefault ();
291 bool list
= defaultValueType
.IsArray
;
293 var inner_type
= i_enumerable_interface
.GetGenericArguments () [0];
294 return "a" + GetGcType (inner_type
);
296 return GetGcType (defaultValueType
);
299 internal static string GetDefault (object defaultValue
, Type defaultValueType
)
301 bool list
= defaultValueType
.IsArray
;
303 string str_val
= null;
306 if (defaultValue
== null || ((object[])defaultValue
).Length
== 0) {
309 var type
= Type
.GetTypeArray ((object [])defaultValue
) [0];
311 object [] arr
= (object [])defaultValue
;
312 for (int i
= 0; i
< arr
.Length
; i
++) {
313 str_val
+= GetValueString (type
, arr
[i
]).Replace (",", "\\,");
314 if (i
< arr
.Length
- 1) {
321 str_val
= GetValueString (defaultValueType
, defaultValue
);
326 private static string CamelCaseToUnderScoreLowerCase (string s
)
328 string undercase
= String
.Empty
;
329 string [] tokens
= Regex
.Split (s
, "([A-Z]{1}[a-z]+)");
331 for(int i
= 0; i
< tokens
.Length
; i
++) {
332 if (tokens
[i
] == String
.Empty
) {
336 undercase
+= tokens
[i
].ToLower();
337 if (i
< tokens
.Length
- 2) {