public void Run(string [] args)
        {
            this.sdk = AndroidSdkStructure.FromSdkHome(args [0]);
            this.additional_libraries = args.Skip(1);
            var missings = additional_libraries.Where(f => !File.Exists(f));

            if (missings.Any())
            {
                throw new ArgumentException($"One or more specified additional libraries do not exist: {string.Join ("", "", missings)}");
            }

            Console.WriteLine($"Android SDK: {sdk.Home}");
            Console.WriteLine($"Latest platform: {sdk.LatestPlatform}");
            foreach (var extlib in sdk.ExtraLibrariesVersionSpecific)
            {
                Console.WriteLine($"  Extra: {extlib}");
            }

            foreach (var wi in sdk.Widgets)
            {
                Console.WriteLine($"  WidgetType: {wi.Kind} {wi.FullName} -extends- {wi.BaseTypeName}");
            }

            foreach (var ds in sdk.DeclaredStyleables)
            {
                Console.WriteLine($"  Declared Styleable: {ds.Name}");
            }

            new SchemaGenerator().Generate(sdk, "generated");
        }
        void GenerateDefaultNamespaceFile(AndroidSdkStructure sdk, string defaultNamespaceFile)
        {
            var dir = Path.GetDirectoryName(defaultNamespaceFile);

            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }

            var xs = new XmlSchema();

            xs.Namespaces.Add("android", androidNS);

            Func <string, XmlQualifiedName> getTypeQName = s => s == null ? new XmlQualifiedName("anyType", XmlSchema.Namespace) : new XmlQualifiedName(s + "_Type");

            foreach (var vt in sdk.Widgets)
            {
                var typeName = GetSchemaTypeName(vt.FullName);
                var xe       = new XmlSchemaElement {
                    Name           = typeName,
                    SchemaTypeName = getTypeQName(typeName)
                };
                var content = new XmlSchemaComplexContentExtension {
                    BaseTypeName = getTypeQName(GetSchemaTypeName(vt.BaseTypeName))
                };
                if (sdk.DeclaredStyleables.Any(ds => ds.Name == typeName))
                {
                    content.Attributes.Add(new XmlSchemaAttributeGroupRef {
                        RefName = new XmlQualifiedName(typeName, androidNS)
                    });
                }
                var xt = new XmlSchemaComplexType {
                    Name         = getTypeQName(typeName).Name,
                    ContentModel = new XmlSchemaComplexContent {
                        Content = content,
                    },
                };
                xs.Items.Add(xe);
                xs.Items.Add(xt);
            }
            using (var writer = XmlWriter.Create(defaultNamespaceFile, new XmlWriterSettings {
                Indent = true
            }))
                xs.Write(writer);
        }
 public void Generate(AndroidSdkStructure sdk, string defaultNamespaceFile, string androidNamespaceFile)
 {
     GenerateAndroidAttributesFile(sdk, androidNamespaceFile);
     GenerateDefaultNamespaceFile(sdk, defaultNamespaceFile);
 }
 public void Generate(AndroidSdkStructure sdk, string outputDirectory)
 {
     Generate(sdk, Path.Combine(outputDirectory, "android-layout.xsd"), Path.Combine(outputDirectory, "android-attributes.xsd"));
 }
        void GenerateAndroidAttributesFile(AndroidSdkStructure sdk, string androidNamespaceFile)
        {
            var xs = new XmlSchema {
                TargetNamespace = androidNS
            };

            xs.Namespaces.Add("android", androidNS);

            foreach (var name in new string [] { "color", "reference", "dimension", "fraction" })
            {
                xs.Items.Add(new XmlSchemaSimpleType {
                    Name    = name,
                    Content = new XmlSchemaSimpleTypeRestriction {
                        BaseTypeName = new XmlQualifiedName("string", XmlSchema.Namespace)
                    },
                });
            }

            // We cannot directly define global attributes within this attributeGroup, because such an attribute will become "local".
            // It first needs to be defined globally and then can be referenced within the attributeGroup.
            // Therefore, those attributes within styleables are first flattened and then added globally.
            var existing = new List <AndroidSdkStructure.Attribute> ();

            foreach (var attr in sdk.DeclaredStyleables.SelectMany(ds => ds.Attributes))
            {
                if (existing.Any(e => e.Name == attr.Name))
                {
                    // FIXME: check if the content types are equivalent.
                    continue;
                }
                existing.Add(attr);
                var est = attr.Enumerations != null && attr.Enumerations.Any() ? new XmlSchemaSimpleType {
                    Name = attr.Name + "_values"
                } : null;
                if (est != null)
                {
                    var str = new XmlSchemaSimpleTypeRestriction {
                        BaseTypeName = new XmlQualifiedName("string", XmlSchema.Namespace)
                    };
                    est.Content = str;
                    foreach (var e in attr.Enumerations)
                    {
                        str.Facets.Add(new XmlSchemaEnumerationFacet {
                            Value = e.Name
                        });
                    }
                    xs.Items.Add(est);
                }
                var ad = new XmlSchemaAttribute {
                    Name = attr.Name,
                    // FIXME: handle union of formats,
                    SchemaTypeName = attr.Enumerations.Any() || !attr.Formats.Any() ? null : new XmlQualifiedName(attr.Formats [0].XsdType),
                    SchemaType     = attr.Enumerations.Any() ?
                                     new XmlSchemaSimpleType {
                        Content = attr.Formats.FirstOrDefault()?.Name == "enum" ?
                                  (XmlSchemaSimpleTypeContent)
                                  new XmlSchemaSimpleTypeRestriction {
                            BaseTypeName = new XmlQualifiedName(est.Name, androidNS)
                        } :
                        new XmlSchemaSimpleTypeList {
                            ItemTypeName = new XmlQualifiedName(est.Name, androidNS)
                        }
                    } : null,
                };
                xs.Items.Add(ad);
            }
            foreach (var ds in sdk.DeclaredStyleables)
            {
                var ag = new XmlSchemaAttributeGroup {
                    Name = ds.Name ?? "__global__",
                };
                foreach (var attr in ds.Attributes)
                {
                    ag.Attributes.Add(new XmlSchemaAttribute {
                        RefName = new XmlQualifiedName(attr.Name, androidNS)
                    });
                }
                xs.Items.Add(ag);
            }
            using (var writer = XmlWriter.Create(androidNamespaceFile, new XmlWriterSettings {
                Indent = true
            }))
                xs.Write(writer);
        }