You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by dk...@apache.org on 2018/12/05 14:54:06 UTC

[avro] branch master updated: AVRO-2156: Map Avro namespace to C# namespaces during code generation

This is an automated email from the ASF dual-hosted git repository.

dkulp pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/avro.git


The following commit(s) were added to refs/heads/master by this push:
     new 602a2c5  AVRO-2156: Map Avro namespace to C# namespaces during code generation
602a2c5 is described below

commit 602a2c5b5258d5e1f0f60f71506b16801cbdf156
Author: Brian Lachniet <bl...@gmail.com>
AuthorDate: Sat Mar 10 18:34:49 2018 -0500

    AVRO-2156: Map Avro namespace to C# namespaces during code generation
---
 lang/csharp/src/apache/codegen/AvroGen.cs         | 111 ++++++++++++++++++++--
 lang/csharp/src/apache/main/CodeGen/CodeGen.cs    |  12 ++-
 lang/csharp/src/apache/test/CodGen/CodeGenTest.cs |  37 ++++++++
 3 files changed, 150 insertions(+), 10 deletions(-)

diff --git a/lang/csharp/src/apache/codegen/AvroGen.cs b/lang/csharp/src/apache/codegen/AvroGen.cs
index 033b840..465857f 100644
--- a/lang/csharp/src/apache/codegen/AvroGen.cs
+++ b/lang/csharp/src/apache/codegen/AvroGen.cs
@@ -25,25 +25,111 @@ namespace Avro
     {
         static void Main(string[] args)
         {
-            if (args.Length != 3)
+            // Print usage if no arguments provided or help requested
+            if (args.Length == 0 || args[0] == "-h" || args[0] == "--help")
             {
                 Usage();
                 return;
             }
-            if (args[0] == "-p")
-                GenProtocol(args[1], args[2]);
-            else if (args[0] == "-s")
-                GenSchema(args[1], args[2]);
-            else
+
+            // Parse command line arguments
+            bool? isProtocol = null;
+            string inputFile = null;
+            string outputDir = null;
+            var namespaceMapping = new Dictionary<string, string>();
+            for (int i = 0; i < args.Length; ++i)
+            {
+                if (args[i] == "-p")
+                {
+                    if (i + 1 >= args.Length)
+                    {
+                        Console.WriteLine("Missing path to protocol file");
+                        Usage();
+                        return;
+                    }
+
+                    isProtocol = true;
+                    inputFile = args[++i];
+                }
+                else if (args[i] == "-s")
+                {
+                    if (i + 1 >= args.Length)
+                    {
+                        Console.WriteLine("Missing path to schema file");
+                        Usage();
+                        return;
+                    }
+
+                    isProtocol = false;
+                    inputFile = args[++i];
+                }
+                else if (args[i] == "--namespace")
+                {
+                    if (i + 1 >= args.Length)
+                    {
+                        Console.WriteLine("Missing namespace mapping");
+                        Usage();
+                        return;
+                    }
+
+                    var parts = args[++i].Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
+                    if (parts.Length != 2)
+                    {
+                        Console.WriteLine("Malformed namespace mapping. Required format is \"avro.namespace:csharp.namespace\"");
+                        Usage();
+                        return;
+                    }
+
+                    namespaceMapping[parts[0]] = parts[1];
+                }
+                else if (outputDir == null)
+                {
+                    outputDir = args[i];
+                }
+                else
+                {
+                    Console.WriteLine("Unexpected command line argument: {0}", args[i]);
+                    Usage();
+                }
+            }
+
+            // Ensure we got all the command line arguments we need
+            bool isValid = true;
+            if (!isProtocol.HasValue || inputFile == null)
+            {
+                Console.WriteLine("Must provide either '-p <protocolfile>' or '-s <schemafile>'");
+                isValid = false;
+            }
+            else if (outputDir == null)
+            {
+                Console.WriteLine("Must provide 'outputdir'");
+                isValid = false;
+            }
+
+            if (!isValid)
                 Usage();
+            else if (isProtocol.Value)
+                GenProtocol(inputFile, outputDir, namespaceMapping);
+            else
+                GenSchema(inputFile, outputDir, namespaceMapping);
         }
 
         static void Usage()
         {
-            Console.WriteLine("Usage:\navrogen -p <protocolfile> <outputdir>\navrogen -s <schemafile> <outputdir>");
+            Console.WriteLine("{0}\n\n" +
+                "Usage:\n" +
+                "  avrogen -p <protocolfile> <outputdir> [--namespace <my.avro.ns:my.csharp.ns>]\n" +
+                "  avrogen -s <schemafile> <outputdir> [--namespace <my.avro.ns:my.csharp.ns>]\n\n" +
+                "Options:\n" +
+                "  -h --help   Show this screen.\n" +
+                "  --namespace Map an Avro schema/protocol namespace to a C# namespace.\n" +
+                "              The format is \"my.avro.namespace:my.csharp.namespace\".\n" +
+                "              May be specified multiple times to map multiple namespaces.\n",
+                AppDomain.CurrentDomain.FriendlyName);
             return;
         }
-        static void GenProtocol(string infile, string outdir)
+        static void GenProtocol(string infile, string outdir,
+            IEnumerable<KeyValuePair<string, string>> namespaceMapping)
         {
             try
             {
@@ -53,6 +139,9 @@ namespace Avro
                 CodeGen codegen = new CodeGen();
                 codegen.AddProtocol(protocol);
 
+                foreach (var entry in namespaceMapping)
+                    codegen.NamespaceMapping[entry.Key] = entry.Value;
+
                 codegen.GenerateCode();
                 codegen.WriteTypes(outdir);
             }
@@ -61,7 +150,8 @@ namespace Avro
                 Console.WriteLine("Exception occurred. " + ex.Message);
             }
         }
-        static void GenSchema(string infile, string outdir)
+        static void GenSchema(string infile, string outdir,
+            IEnumerable<KeyValuePair<string, string>> namespaceMapping)
         {
             try
             {
@@ -71,6 +161,9 @@ namespace Avro
                 CodeGen codegen = new CodeGen();
                 codegen.AddSchema(schema);
 
+                foreach (var entry in namespaceMapping)
+                    codegen.NamespaceMapping[entry.Key] = entry.Value;
+
                 codegen.GenerateCode();
                 codegen.WriteTypes(outdir);
             }
diff --git a/lang/csharp/src/apache/main/CodeGen/CodeGen.cs b/lang/csharp/src/apache/main/CodeGen/CodeGen.cs
index 2bcebab..c576200 100644
--- a/lang/csharp/src/apache/main/CodeGen/CodeGen.cs
+++ b/lang/csharp/src/apache/main/CodeGen/CodeGen.cs
@@ -45,6 +45,11 @@ namespace Avro
         public IList<Protocol> Protocols { get; private set; }
 
         /// <summary>
+        /// Mapping of Avro namespaces to C# namespaces
+        /// </summary>
+        public IDictionary<string, string> NamespaceMapping { get; private set; }
+
+        /// <summary>
         /// List of generated namespaces
         /// </summary>
         protected Dictionary<string, CodeNamespace> namespaceLookup = new Dictionary<string, CodeNamespace>(StringComparer.Ordinal);
@@ -56,6 +61,7 @@ namespace Avro
         {
             this.Schemas = new List<Schema>();
             this.Protocols = new List<Protocol>();
+            this.NamespaceMapping = new Dictionary<string, string>();
         }
 
         /// <summary>
@@ -90,7 +96,11 @@ namespace Avro
 
             if (!namespaceLookup.TryGetValue(name, out ns))
             {
-                ns = new CodeNamespace(CodeGenUtil.Instance.Mangle(name));
+                string csharpNamespace;
+                ns = NamespaceMapping.TryGetValue(name, out csharpNamespace)
+                    ? new CodeNamespace(csharpNamespace)
+                    : new CodeNamespace(CodeGenUtil.Instance.Mangle(name));
+
                 foreach (CodeNamespaceImport nci in CodeGenUtil.Instance.NamespaceImports)
                     ns.Imports.Add(nci);
 
diff --git a/lang/csharp/src/apache/test/CodGen/CodeGenTest.cs b/lang/csharp/src/apache/test/CodGen/CodeGenTest.cs
index c5428b3..f1141db 100644
--- a/lang/csharp/src/apache/test/CodGen/CodeGenTest.cs
+++ b/lang/csharp/src/apache/test/CodGen/CodeGenTest.cs
@@ -98,6 +98,43 @@ namespace Avro.Test
             }
         }
 
+        [TestCase(@"{
+""type"": ""fixed"",
+""namespace"": ""com.base"",
+""name"": ""MD5"",
+""size"": 16
+}", null, null, "com.base")]
+        [TestCase(@"{
+""type"": ""fixed"",
+""namespace"": ""com.base"",
+""name"": ""MD5"",
+""size"": 16
+}", "com.base", "SchemaTest", "SchemaTest")]
+        [TestCase(@"{
+""type"": ""fixed"",
+""namespace"": ""com.base"",
+""name"": ""MD5"",
+""size"": 16
+}", "miss", "SchemaTest", "com.base")]
+        public void TestCodeGenNamespaceMapping(string str, string avroNamespace, string csharpNamespace,
+            string expectedNamespace)
+        {
+            Schema schema = Schema.Parse(str);
+
+            var codegen = new CodeGen();
+            codegen.AddSchema(schema);
+
+            if (avroNamespace != null && csharpNamespace != null)
+            {
+                codegen.NamespaceMapping[avroNamespace] = csharpNamespace;
+            }
+
+            var results = GenerateAssembly(codegen);
+            foreach(var type in results.CompiledAssembly.GetTypes())
+            {
+                Assert.AreEqual(expectedNamespace, type.Namespace);
+            }
+        }
 
         private static CompilerResults GenerateSchema(Schema schema)
         {