static string NormalizeAlternative(string value)
        {
            int s = value.IndexOfAny(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar });

            if (s < 0)
            {
                return(value);
            }

            int a = value.IndexOf('-');

            return
                (JavaResourceParser.GetNestedTypeName(value.Substring(0, (a < 0 || a >= s) ? s : a)).ToLowerInvariant() +
                 value.Substring(s));
        }
        public override bool Execute()
        {
            // In Xamarin Studio, if the project name isn't a valid C# identifier
            // then $(RootNamespace) is not set, and the generated Activity is
            // placed into the "Application" namespace. VS just munges the project
            // name to be a valid C# identifier.
            // Use "Application" as the default namespace name to work with XS.
            Namespace = Namespace ?? "Application";

            Log.LogDebugMessage("GenerateResourceDesigner Task");
            Log.LogDebugMessage("  NetResgenOutputFile: {0}", NetResgenOutputFile);
            Log.LogDebugMessage("  JavaResgenInputFile: {0}", JavaResgenInputFile);
            Log.LogDebugMessage("  Namespace: {0}", Namespace);
            Log.LogDebugMessage("  ResourceDirectory: {0}", ResourceDirectory);
            Log.LogDebugTaskItemsAndLogical("  AdditionalResourceDirectories:", AdditionalResourceDirectories);
            Log.LogDebugMessage("  IsApplication: {0}", IsApplication);
            Log.LogDebugMessage("  UseManagedResourceGenerator: {0}", UseManagedResourceGenerator);
            Log.LogDebugTaskItemsAndLogical("  Resources:", Resources);
            Log.LogDebugTaskItemsAndLogical("  References:", References);

            if (!File.Exists(JavaResgenInputFile) && !UseManagedResourceGenerator)
            {
                return(true);
            }

            // ResourceDirectory may be a relative path, and
            // we need to compare it to absolute paths
            ResourceDirectory = Path.GetFullPath(ResourceDirectory);

            // Create our capitalization maps so we can support mixed case resources
            foreach (var item in Resources)
            {
                if (!item.ItemSpec.StartsWith(ResourceDirectory))
                {
                    continue;
                }

                var name         = item.ItemSpec.Substring(ResourceDirectory.Length);
                var logical_name = item.GetMetadata("LogicalName").Replace('\\', '/');

                AddRename(name.Replace('/', Path.DirectorySeparatorChar), logical_name.Replace('/', Path.DirectorySeparatorChar));
            }
            if (AdditionalResourceDirectories != null)
            {
                foreach (var additionalDir in AdditionalResourceDirectories)
                {
                    var file = Path.Combine(ProjectDir, Path.GetDirectoryName(additionalDir.ItemSpec), "__res_name_case_map.txt");
                    if (File.Exists(file))
                    {
                        foreach (var line in File.ReadAllLines(file).Where(l => !string.IsNullOrEmpty(l)))
                        {
                            string [] tok = line.Split(';');
                            AddRename(tok [1].Replace('/', Path.DirectorySeparatorChar), tok [0].Replace('/', Path.DirectorySeparatorChar));
                        }
                    }
                }
            }

            // Parse out the resources from the R.java file
            CodeTypeDeclaration resources;

            if (UseManagedResourceGenerator)
            {
                var parser = new ManagedResourceParser()
                {
                    Log = Log
                };
                resources = parser.Parse(ResourceDirectory, AdditionalResourceDirectories?.Select(x => x.ItemSpec), IsApplication, resource_fixup);
            }
            else
            {
                var parser = new JavaResourceParser()
                {
                    Log = Log
                };
                resources = parser.Parse(JavaResgenInputFile, IsApplication, resource_fixup);
            }

            var  extension = Path.GetExtension(NetResgenOutputFile);
            var  language  = string.Compare(extension, ".fs", StringComparison.OrdinalIgnoreCase) == 0 ? "F#" : CodeDomProvider.GetLanguageFromExtension(extension);
            bool isVB      = string.Equals(extension, ".vb", StringComparison.OrdinalIgnoreCase);
            bool isFSharp  = string.Equals(language, "F#", StringComparison.OrdinalIgnoreCase);
            bool isCSharp  = string.Equals(language, "C#", StringComparison.OrdinalIgnoreCase);

            // Let VB put this in the default namespace
            if (isVB)
            {
                Namespace = string.Empty;
            }

            // Create static resource overwrite methods for each Resource class in libraries.
            var assemblyNames = new List <string> ();

            if (IsApplication && References != null && References.Any())
            {
                // FIXME: should this be unified to some better code with ResolveLibraryProjectImports?
                using (var resolver = new DirectoryAssemblyResolver(this.CreateTaskLogger(), loadDebugSymbols: false)) {
                    foreach (var assemblyName in References)
                    {
                        var    suffix   = assemblyName.ItemSpec.EndsWith(".dll") ? String.Empty : ".dll";
                        string hintPath = assemblyName.GetMetadata("HintPath").Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
                        string fileName = assemblyName.ItemSpec + suffix;
                        string fullPath = Path.GetFullPath(assemblyName.ItemSpec);
                        // Skip non existing files in DesignTimeBuild
                        if (!File.Exists(fullPath) && DesignTimeBuild)
                        {
                            Log.LogDebugMessage("Skipping non existant dependancy '{0}' due to design time build.", fullPath);
                            continue;
                        }
                        resolver.Load(fullPath);
                        if (!String.IsNullOrEmpty(hintPath) && !File.Exists(hintPath))                           // ignore invalid HintPath
                        {
                            hintPath = null;
                        }
                        string assemblyPath = String.IsNullOrEmpty(hintPath) ? fileName : hintPath;
                        if (MonoAndroidHelper.IsFrameworkAssembly(fileName) && !MonoAndroidHelper.FrameworkEmbeddedJarLookupTargets.Contains(Path.GetFileName(fileName)))
                        {
                            continue;
                        }
                        Log.LogDebugMessage("Scan assembly {0} for resource generator", fileName);
                        assemblyNames.Add(assemblyPath);
                    }
                    var assemblies = assemblyNames.Select(assembly => resolver.GetAssembly(assembly));
                    new ResourceDesignerImportGenerator(Namespace, resources, Log)
                    .CreateImportMethods(assemblies);
                }
            }

            AdjustConstructor(isFSharp, resources);
            foreach (var member in resources.Members)
            {
                if (member is CodeTypeDeclaration)
                {
                    AdjustConstructor(isFSharp, (CodeTypeDeclaration)member);
                }
            }

            // Write out our Resources.Designer.cs file

            WriteFile(NetResgenOutputFile, resources, language, isFSharp, isCSharp);

            return(!Log.HasLoggedErrors);
        }
        public override bool RunTask()
        {
            // In Xamarin Studio, if the project name isn't a valid C# identifier
            // then $(RootNamespace) is not set, and the generated Activity is
            // placed into the "Application" namespace. VS just munges the project
            // name to be a valid C# identifier.
            // Use "Application" as the default namespace name to work with XS.
            Namespace = Namespace ?? "Application";

            if (!File.Exists(JavaResgenInputFile) && !UseManagedResourceGenerator)
            {
                return(true);
            }

            // ResourceDirectory may be a relative path, and
            // we need to compare it to absolute paths
            ResourceDirectory = Path.GetFullPath(ResourceDirectory);

            var javaPlatformDirectory = Path.GetDirectoryName(JavaPlatformJarPath);

            // Create our capitalization maps so we can support mixed case resources
            foreach (var item in Resources)
            {
                if (!item.ItemSpec.StartsWith(ResourceDirectory))
                {
                    continue;
                }

                var name         = item.ItemSpec.Substring(ResourceDirectory.Length);
                var logical_name = item.GetMetadata("LogicalName").Replace('\\', '/');

                AddRename(name.Replace('/', Path.DirectorySeparatorChar), logical_name.Replace('/', Path.DirectorySeparatorChar));
            }
            if (AdditionalResourceDirectories != null)
            {
                foreach (var additionalDir in AdditionalResourceDirectories)
                {
                    var file = Path.Combine(ProjectDir, Path.GetDirectoryName(additionalDir.ItemSpec), "__res_name_case_map.txt");
                    if (File.Exists(file))
                    {
                        foreach (var line in File.ReadAllLines(file).Where(l => !string.IsNullOrEmpty(l)))
                        {
                            string [] tok = line.Split(';');
                            AddRename(tok [1].Replace('/', Path.DirectorySeparatorChar), tok [0].Replace('/', Path.DirectorySeparatorChar));
                        }
                    }
                }
            }

            // Parse out the resources from the R.java file
            CodeTypeDeclaration resources;

            if (UseManagedResourceGenerator)
            {
                var parser = new ManagedResourceParser()
                {
                    Log = Log, JavaPlatformDirectory = javaPlatformDirectory, ResourceFlagFile = ResourceFlagFile
                };
                resources = parser.Parse(ResourceDirectory, AdditionalResourceDirectories?.Select(x => x.ItemSpec), IsApplication, resource_fixup);
            }
            else
            {
                var parser = new JavaResourceParser()
                {
                    Log = Log
                };
                resources = parser.Parse(JavaResgenInputFile, IsApplication, resource_fixup);
            }

            var  extension = Path.GetExtension(NetResgenOutputFile);
            var  language  = string.Compare(extension, ".fs", StringComparison.OrdinalIgnoreCase) == 0 ? "F#" : CodeDomProvider.GetLanguageFromExtension(extension);
            bool isVB      = string.Equals(extension, ".vb", StringComparison.OrdinalIgnoreCase);
            bool isFSharp  = string.Equals(language, "F#", StringComparison.OrdinalIgnoreCase);
            bool isCSharp  = string.Equals(language, "C#", StringComparison.OrdinalIgnoreCase);


            if (isFSharp)
            {
                language            = "C#";
                isCSharp            = true;
                NetResgenOutputFile = Path.ChangeExtension(NetResgenOutputFile, ".cs");
            }

            // Let VB put this in the default namespace
            if (isVB)
            {
                Namespace = string.Empty;
            }

            List <string> aliases = new List <string> ();

            // Create static resource overwrite methods for each Resource class in libraries.
            if (IsApplication && References != null && References.Length > 0)
            {
                var assemblies = new List <ITaskItem> (References.Length);
                foreach (var assembly in References)
                {
                    var assemblyPath = assembly.ItemSpec;
                    var fileName     = Path.GetFileName(assemblyPath);
                    if (MonoAndroidHelper.IsFrameworkAssembly(fileName) &&
                        !MonoAndroidHelper.FrameworkEmbeddedJarLookupTargets.Contains(fileName))
                    {
                        Log.LogDebugMessage($"Skipping framework assembly '{fileName}'.");
                        continue;
                    }
                    if (!File.Exists(assemblyPath))
                    {
                        Log.LogDebugMessage($"Skipping non-existent dependency '{assemblyPath}'.");
                        continue;
                    }
                    ITaskItem item = new TaskItem(assemblyPath);
                    assembly.CopyMetadataTo(item);
                    assemblies.Add(item);
                    string aliasMetaData = assembly.GetMetadata("Aliases");
                    if (!string.IsNullOrEmpty(aliasMetaData))
                    {
                        foreach (var alias in aliasMetaData.Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries))
                        {
                            string aliasName = alias.Trim();
                            // don't emit an `extern alias global` as it is implicitly done.
                            if (string.Compare("global", aliasName, StringComparison.Ordinal) == 0)
                            {
                                continue;
                            }
                            aliases.Add(aliasName);
                            // only add the first alias for each reference.
                            break;
                        }
                    }
                    Log.LogDebugMessage("Scan assembly {0} for resource generator", fileName);
                }
                new ResourceDesignerImportGenerator(Namespace, resources, Log)
                .CreateImportMethods(assemblies);
            }

            AdjustConstructor(resources);
            foreach (var member in resources.Members)
            {
                if (member is CodeTypeDeclaration)
                {
                    AdjustConstructor((CodeTypeDeclaration)member);
                }
            }

            // Write out our Resources.Designer.cs file

            WriteFile(NetResgenOutputFile, resources, language, isCSharp, aliases);

            return(!Log.HasLoggedErrors);
        }