19 using System.Collections.Generic;
    21 using System.Reflection;
    24 using System.CodeDom.Compiler;
    25 using Microsoft.CSharp;
    40         public IList<Schema> 
Schemas { 
get; 
private set; }
    45         public IList<Protocol> 
Protocols { 
get; 
private set; }
    50         protected Dictionary<string, CodeNamespace> 
namespaceLookup = 
new Dictionary<string, CodeNamespace>(StringComparer.Ordinal);
    57             this.
Schemas = 
new List<Schema>();
    86             if (
string.IsNullOrEmpty(name)) 
    87                 throw new ArgumentNullException(
"name", 
"name cannot be null.");
    89             CodeNamespace ns = 
null;
   125                 foreach (KeyValuePair<SchemaName, NamedSchema> sn 
in names)
   127                     switch (sn.Value.Tag)
   134                             throw new CodeGenException(
"Names in schema should only be of type NamedSchema, type found " + sn.Value.Tag);
   148                 foreach (KeyValuePair<SchemaName, NamedSchema> sn 
in names)
   150                     switch (sn.Value.Tag)
   157                             throw new CodeGenException(
"Names in protocol should only be of type NamedSchema, type found " + sn.Value.Tag);
   221                     foreach (
Field field 
in rs.Fields)
   227                     addName(asc.ItemSchema, names);
   232                     addName(ms.ValueSchema, names);
   237                     foreach (
Schema usc 
in us.Schemas)
   254             if (
null == fixedSchema) 
throw new CodeGenException(
"Unable to cast schema into a fixed");
   256             CodeTypeDeclaration ctd = 
new CodeTypeDeclaration();
   259             ctd.IsPartial = 
true;
   260             ctd.Attributes = MemberAttributes.Public;
   261             ctd.BaseTypes.Add(
"SpecificFixed");
   267             string sizefname = 
"fixedSize";
   268             var ctrfield = 
new CodeTypeReference(typeof(uint));
   269             var codeField = 
new CodeMemberField(ctrfield, sizefname);
   270             codeField.Attributes = MemberAttributes.Private | MemberAttributes.Static;
   271             codeField.InitExpression = 
new CodePrimitiveExpression(fixedSchema.
Size);
   272             ctd.Members.Add(codeField);
   275             var fieldRef = 
new CodeFieldReferenceExpression(
new CodeThisReferenceExpression(), sizefname);
   276             var 
property = 
new CodeMemberProperty();
   277             property.Attributes = MemberAttributes.Public | MemberAttributes.Static;
   278             property.Name = 
"FixedSize";
   279             property.Type = ctrfield;
   280             property.GetStatements.Add(
new CodeMethodReturnStatement(
new CodeTypeReferenceExpression(schema.
Name + 
"." + sizefname)));
   281             ctd.Members.Add(property);
   284             CodeConstructor cc = 
new CodeConstructor();
   285             cc.Attributes = MemberAttributes.Public;
   286             cc.BaseConstructorArgs.Add(
new CodeVariableReferenceExpression(sizefname));
   290             if (
string.IsNullOrEmpty(nspace))
   293             codens.Types.Add(ctd);
   304             if (
null == enumschema) 
throw new CodeGenException(
"Unable to cast schema into an enum");
   308             ctd.Attributes = MemberAttributes.Public;
   310             foreach (
string symbol 
in enumschema.Symbols)
   313                     throw new CodeGenException(
"Enum symbol " + symbol + 
" is a C# reserved keyword");
   314                 CodeMemberField field = 
new CodeMemberField(typeof(
int), symbol);
   315                 ctd.Members.Add(field);
   318             string nspace = enumschema.Namespace;
   319             if (
string.IsNullOrEmpty(nspace))
   320                 throw new CodeGenException(
"Namespace required for enum schema " + enumschema.Name);
   323             codens.Types.Add(ctd);
   331             var ctd = 
new CodeTypeDeclaration(protocolNameMangled);
   332             ctd.TypeAttributes = TypeAttributes.Abstract | TypeAttributes.Public;
   334             ctd.BaseTypes.Add(
"Avro.Specific.ISpecificProtocol");
   336             AddProtocolDocumentation(protocol, ctd);
   339             var protocolField = 
new CodeMemberField();
   340             protocolField.Attributes = MemberAttributes.Private | MemberAttributes.Static | MemberAttributes.Final;
   341             protocolField.Name = 
"protocol";
   342             protocolField.Type = 
new CodeTypeReference(
"readonly Avro.Protocol");
   344             var cpe = 
new CodePrimitiveExpression(protocol.
ToString());
   345             var cmie = 
new CodeMethodInvokeExpression(
   346                 new CodeMethodReferenceExpression(
new CodeTypeReferenceExpression(typeof(
Protocol)), 
"Parse"),
   347                 new CodeExpression[] { cpe });
   349             protocolField.InitExpression = cmie;
   351             ctd.Members.Add(protocolField);
   354             var 
property = 
new CodeMemberProperty();
   355             property.Attributes = MemberAttributes.Public | MemberAttributes.Final;
   356             property.Name = 
"Protocol";
   357             property.Type = 
new CodeTypeReference(
"Avro.Protocol");
   358             property.HasGet = 
true;
   361             property.GetStatements.Add(
new CodeTypeReferenceExpression(
"return protocol"));
   362             ctd.Members.Add(property);
   367             var requestMethod = CreateRequestMethod();
   369             var builder = 
new StringBuilder();
   373                 builder.Append(
"switch(messageName)\n\t\t\t{");
   375                 foreach (var a 
in protocol.
Messages)
   377                     builder.Append(
"\n\t\t\t\tcase \"").Append(a.Key).Append(
"\":\n");
   380                     string type = getType(a.Value.Response, 
false, ref unused);
   382                     builder.Append(
"\t\t\t\trequestor.Request<")
   384                            .Append(
">(messageName, args, callback);\n");
   385                     builder.Append(
"\t\t\t\tbreak;\n");
   388                 builder.Append(
"\t\t\t}");
   390             var cseGet = 
new CodeSnippetExpression(builder.ToString());
   392             requestMethod.Statements.Add(cseGet);
   393             ctd.Members.Add(requestMethod);
   395             AddMethods(protocol, 
false, ctd);
   398             if (
string.IsNullOrEmpty(nspace))
   402             codens.Types.Add(ctd);
   405             ctd = 
new CodeTypeDeclaration(protocolNameMangled + 
"Callback");
   406             ctd.TypeAttributes = TypeAttributes.Abstract | TypeAttributes.Public;
   408             ctd.BaseTypes.Add(protocolNameMangled);
   414             AddProtocolDocumentation(protocol, ctd);
   416             AddMethods(protocol, 
true, ctd);
   418             codens.Types.Add(ctd);
   421         private static CodeMemberMethod CreateRequestMethod()
   423             var requestMethod = 
new CodeMemberMethod();
   424             requestMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
   425             requestMethod.Name = 
"Request";
   426             requestMethod.ReturnType = 
new CodeTypeReference(typeof (
void));
   430                 requestMethod.Parameters.Add(requestor);
   432                 var messageName = 
new CodeParameterDeclarationExpression(typeof (
string), 
"messageName");
   433                 requestMethod.Parameters.Add(messageName);
   435                 var args = 
new CodeParameterDeclarationExpression(typeof (
object[]), 
"args");
   436                 requestMethod.Parameters.Add(args);
   438                 var callback = 
new CodeParameterDeclarationExpression(typeof (
object), 
"callback");
   439                 requestMethod.Parameters.Add(callback);
   441             return requestMethod;
   444         private static void AddMethods(Protocol protocol, 
bool generateCallback, CodeTypeDeclaration ctd)
   446             foreach (var e 
in protocol.Messages)
   449                 var message = e.Value;
   450                 var response = message.Response;
   452                 if (generateCallback && message.Oneway.GetValueOrDefault())
   455                 var messageMember = 
new CodeMemberMethod();
   456                 messageMember.Name = CodeGenUtil.Instance.Mangle(name);
   457                 messageMember.Attributes = MemberAttributes.Public | MemberAttributes.Abstract;
   459                 if (message.Doc!= 
null && message.Doc.Trim() != 
string.Empty)
   460                     messageMember.Comments.Add(
new CodeCommentStatement(message.Doc));
   462                 if (message.Oneway.GetValueOrDefault() || generateCallback)
   464                     messageMember.ReturnType = 
new CodeTypeReference(typeof (
void));
   468                     bool ignored = 
false;
   469                     string type = getType(response, 
false, ref ignored);
   471                     messageMember.ReturnType = 
new CodeTypeReference(type);
   474                 foreach (Field field 
in message.Request.Fields)
   476                     bool ignored = 
false;
   477                     string type = getType(field.Schema, 
false, ref ignored);
   479                     string fieldName = CodeGenUtil.Instance.Mangle(field.Name);
   480                     var parameter = 
new CodeParameterDeclarationExpression(type, fieldName);
   481                     messageMember.Parameters.Add(parameter);
   484                 if (generateCallback)
   487                     var type = getType(response, 
false, ref unused);
   488                     var parameter = 
new CodeParameterDeclarationExpression(
"Avro.IO.ICallback<" + type + 
">",
   490                     messageMember.Parameters.Add(parameter);
   494                 ctd.Members.Add(messageMember);
   498         private void AddProtocolDocumentation(Protocol protocol, CodeTypeDeclaration ctd)
   501             if (protocol.Doc != 
null && protocol.Doc.Trim() != 
string.Empty)
   504                 if (interfaceDoc != 
null)
   505                     ctd.Comments.Add(interfaceDoc);
   518             if (
null == recordSchema) 
throw new CodeGenException(
"Unable to cast schema into a record");
   524             ctd.BaseTypes.Add(isError ? 
"SpecificException" : 
"ISpecificRecord");
   526             ctd.Attributes = MemberAttributes.Public;
   528             ctd.IsPartial = 
true;
   533             var cmmGet = 
new CodeMemberMethod();
   535             cmmGet.Attributes = MemberAttributes.Public;
   536             cmmGet.ReturnType = 
new CodeTypeReference(
"System.Object");
   537             cmmGet.Parameters.Add(
new CodeParameterDeclarationExpression(typeof(
int), 
"fieldPos"));
   538             StringBuilder getFieldStmt = 
new StringBuilder(
"switch (fieldPos)\n\t\t\t{\n");
   541             var cmmPut = 
new CodeMemberMethod();
   543             cmmPut.Attributes = MemberAttributes.Public;
   544             cmmPut.ReturnType = 
new CodeTypeReference(typeof(
void));
   545             cmmPut.Parameters.Add(
new CodeParameterDeclarationExpression(typeof(
int), 
"fieldPos"));
   546             cmmPut.Parameters.Add(
new CodeParameterDeclarationExpression(
"System.Object", 
"fieldValue"));
   547             var putFieldStmt = 
new StringBuilder(
"switch (fieldPos)\n\t\t\t{\n");
   551                 cmmGet.Attributes |= MemberAttributes.Override;
   552                 cmmPut.Attributes |= MemberAttributes.Override;
   555             foreach (
Field field 
in recordSchema.Fields)
   558                 bool nullibleEnum = 
false;
   559                 string baseType = getType(field.
Schema, 
false, ref nullibleEnum);
   560                 var ctrfield = 
new CodeTypeReference(baseType);
   563                 string privFieldName = 
string.Concat(
"_", field.
Name);
   564                 var codeField = 
new CodeMemberField(ctrfield, privFieldName);
   565                 codeField.Attributes = MemberAttributes.Private;
   568                 CodeCommentStatement propertyComment = 
null;
   572                     if (
null != propertyComment)
   573                         codeField.Comments.Add(propertyComment);
   577                 ctd.Members.Add(codeField);
   580                 var fieldRef = 
new CodeFieldReferenceExpression(
new CodeThisReferenceExpression(), privFieldName);
   584                 var 
property = 
new CodeMemberProperty();
   585                 property.Attributes = MemberAttributes.Public | MemberAttributes.Final;
   586                 property.Name = mangledName;
   587                 property.Type = ctrfield;
   588                 property.GetStatements.Add(
new CodeMethodReturnStatement(fieldRef));
   589                 property.SetStatements.Add(
new CodeAssignStatement(fieldRef, 
new CodePropertySetValueReferenceExpression()));
   590                 if (
null != propertyComment)
   591                     property.Comments.Add(propertyComment);
   594                 ctd.Members.Add(property);
   597                 getFieldStmt.Append(
"\t\t\tcase ");
   598                 getFieldStmt.Append(field.
Pos);
   599                 getFieldStmt.Append(
": return this.");
   600                 getFieldStmt.Append(mangledName);
   601                 getFieldStmt.Append(
";\n");
   604                 putFieldStmt.Append(
"\t\t\tcase ");
   605                 putFieldStmt.Append(field.
Pos);
   606                 putFieldStmt.Append(
": this.");
   607                 putFieldStmt.Append(mangledName);
   611                     putFieldStmt.Append(
" = fieldValue == null ? (");
   612                     putFieldStmt.Append(baseType);
   613                     putFieldStmt.Append(
")null : (");
   615                     string type = baseType.Remove(0, 16);  
   616                     type = type.Remove(type.Length - 1);   
   618                     putFieldStmt.Append(type);
   619                     putFieldStmt.Append(
")fieldValue; break;\n");
   623                     putFieldStmt.Append(
" = (");
   624                     putFieldStmt.Append(baseType);
   625                     putFieldStmt.Append(
")fieldValue; break;\n");
   630             getFieldStmt.Append(
"\t\t\tdefault: throw new AvroRuntimeException(\"Bad index \" + fieldPos + \" in Get()\");\n\t\t\t}");
   631             var cseGet = 
new CodeSnippetExpression(getFieldStmt.ToString());
   632             cmmGet.Statements.Add(cseGet);
   633             ctd.Members.Add(cmmGet);
   636             putFieldStmt.Append(
"\t\t\tdefault: throw new AvroRuntimeException(\"Bad index \" + fieldPos + \" in Put()\");\n\t\t\t}");
   637             var csePut = 
new CodeSnippetExpression(putFieldStmt.ToString());
   638             cmmPut.Statements.Add(csePut);
   639             ctd.Members.Add(cmmPut);
   641             string nspace = recordSchema.Namespace;
   642             if (
string.IsNullOrEmpty(nspace))
   643                 throw new CodeGenException(
"Namespace required for record schema " + recordSchema.Name);
   646             codens.Types.Add(ctd);
   657         internal static string getType(
Schema schema, 
bool nullible, ref 
bool nullibleEnum)
   662                     return "System.Object";
   664                     if (nullible) 
return "System.Nullable<bool>";
   665                     else return typeof(
bool).ToString();
   667                     if (nullible) 
return "System.Nullable<int>";
   668                     else return typeof(
int).ToString();
   670                     if (nullible) 
return "System.Nullable<long>";
   671                     else return typeof(
long).ToString();
   673                     if (nullible) 
return "System.Nullable<float>";
   674                     else return typeof(
float).ToString();
   676                     if (nullible) 
return "System.Nullable<double>";
   677                     else return typeof(
double).ToString();
   680                     return typeof(
byte[]).ToString();
   682                     return typeof(
string).ToString();
   686                     if (
null == namedSchema)
   693                     else return CodeGenUtil.Instance.Mangle(namedSchema.Fullname);
   695                 case Schema.Type.Fixed:
   696                 case Schema.Type.Record:
   697                 case Schema.Type.Error:
   698                     namedSchema = schema as NamedSchema;
   699                     if (
null == namedSchema)
   700                         throw new CodeGenException(
"Unable to cast schema into a named schema");
   701                     return CodeGenUtil.Instance.Mangle(namedSchema.Fullname);
   703                 case Schema.Type.Array:
   704                     var arraySchema = schema as ArraySchema;
   705                     if (
null == arraySchema)
   706                         throw new CodeGenException(
"Unable to cast schema into an array schema");
   708                     return "IList<" + getType(arraySchema.ItemSchema, 
false, ref nullibleEnum) + 
">";
   710                 case Schema.Type.Map:
   711                     var mapSchema = schema as MapSchema;
   712                     if (
null == mapSchema)
   713                         throw new CodeGenException(
"Unable to cast schema into a map schema");
   714                     return "IDictionary<string," + getType(mapSchema.ValueSchema, 
false, ref nullibleEnum) + 
">";
   716                 case Schema.Type.Union:
   717                     var unionSchema = schema as UnionSchema;
   718                     if (
null == unionSchema)
   719                         throw new CodeGenException(
"Unable to cast schema into a union schema");
   721                     if (
null == nullibleType)
   722                         return CodeGenUtil.Object;
   724                         return getType(nullibleType, 
true, ref nullibleEnum);
   726             throw new CodeGenException(
"Unable to generate CodeTypeReference for " + schema.
Name + 
" type " + schema.
Tag);
   737             if (schema.
Count == 2)
   739                 bool nullable = 
false;
   761             var ctrfield = 
new CodeTypeReference(
"Schema");
   762             string schemaFname = 
"_SCHEMA";
   763             var codeField = 
new CodeMemberField(ctrfield, schemaFname);
   764             codeField.Attributes = MemberAttributes.Public | MemberAttributes.Static;
   766             var cpe = 
new CodePrimitiveExpression(schema.
ToString());
   767             var cmie = 
new CodeMethodInvokeExpression(
   768                 new CodeMethodReferenceExpression(
new CodeTypeReferenceExpression(typeof(
Schema)), 
"Parse"),
   769                 new CodeExpression[] { cpe });
   770             codeField.InitExpression = cmie;
   771             ctd.Members.Add(codeField);
   774             var 
property = 
new CodeMemberProperty();
   775             property.Attributes = MemberAttributes.Public;
   776             if (overrideFlag) 
property.Attributes |= MemberAttributes.Override;
   777             property.Name = 
"Schema";
   778             property.Type = ctrfield;
   780             property.GetStatements.Add(
new CodeMethodReturnStatement(
new CodeTypeReferenceExpression(ctd.Name + 
"." + schemaFname)));
   781             ctd.Members.Add(property);
   791             string text = 
string.Format(
"<summary>\r\n {0}\r\n </summary>", comment);
   792             return new CodeCommentStatement(text, 
true);
   801             var cscp = 
new CSharpCodeProvider();
   803             var opts = 
new CodeGeneratorOptions();
   804             opts.BracingStyle = 
"C";
   805             opts.IndentString = 
"\t";
   806             opts.BlankLinesBetweenMembers = 
false;
   808             using (var outfile = 
new StreamWriter(outputFile))
   810                 cscp.GenerateCodeFromCompileUnit(
CompileUnit, outfile, opts);
   820             var cscp = 
new CSharpCodeProvider();
   822             var opts = 
new CodeGeneratorOptions();
   823             opts.BracingStyle = 
"C";
   824             opts.IndentString = 
"\t";
   825             opts.BlankLinesBetweenMembers = 
false;
   827             CodeNamespaceCollection nsc = 
CompileUnit.Namespaces;
   828             for (
int i = 0; i < nsc.Count; i++)
   833                 Directory.CreateDirectory(dir);
   835                 var new_ns = 
new CodeNamespace(ns.Name);
   838                     new_ns.Imports.Add(nci);
   840                 var types = ns.Types;
   841                 for (
int j = 0; j < types.Count; j++)
   845                     using (var writer = 
new StreamWriter(file, 
false))
   847                         new_ns.Types.Add(ctd);
   848                         cscp.GenerateCodeFromNamespace(new_ns, writer, opts);
   849                         new_ns.Types.Remove(ctd);
 virtual CodeNamespace addNamespace(string name)
Adds a namespace object for the given name into the dictionary if it doesn't exist yet
 
virtual SchemaNames generateNames(Protocol protocol)
Generate list of named schemas from given protocol
 
Schema Schema
Field type's schema
 
Class for fields defined in a record
 
virtual CodeCommentStatement createDocComment(string comment)
Creates an XML documentation for the given comment
 
Class for enum type schemas
 
virtual void createSchemaField(Schema schema, CodeTypeDeclaration ctd, bool overrideFlag)
Creates the static schema field for class types
 
IList< Schema > Types
List of schemas objects representing the different schemas defined under the 'types' attribute
 
CodeGen()
Default constructor
 
virtual CodeTypeDeclaration processRecord(Schema schema)
Creates a class declaration
 
virtual SchemaNames generateNames(Schema schema)
Generate list of named schemas from given schema
 
int Pos
Position of the field within its record.
 
Base class for all schema types
 
bool Contains(SchemaName name)
Checks if given name is in the map
 
string Name
Name of the protocol
 
CodeNamespaceImport [] NamespaceImports
 
override string Name
Name of the schema
 
readonly string Name
Name of the field.
 
IList< Schema > Schemas
List of schemas in the union
 
A singleton class containing data used by codegen
 
CodeCompileUnit CompileUnit
Object that contains all the generated types
 
IList< Protocol > Protocols
List of protocols to generate code for
 
virtual void processInterface(Protocol protocol)
 
Type
Enum for schema types
 
int Size
Fixed size for the bytes
 
Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.
 
CodeCommentStatement FileComment
 
override string ToString()
Returns the canonical JSON representation of this schema.
 
static Schema getNullableType(UnionSchema schema)
Gets the schema of a union with null
 
virtual void AddSchema(Schema schema)
Adds a schema object to generate code for
 
virtual void processFixed(Schema schema)
Creates a class declaration for fixed schema
 
string Namespace
Namespace of the schema
 
Class for array type schemas
 
A class that contains a list of named schemas.
 
string UnMangle(string name)
Remove all the @
 
virtual void processProtocols()
Generates code for the protocol objects
 
IList< Schema > Schemas
List of schemas to generate code for
 
override string ToString()
Writes Protocol in JSON format
 
virtual void addName(Schema schema, SchemaNames names)
Recursively search the given schema for named schemas and adds them to the given container
 
bool Add(SchemaName name, NamedSchema schema)
Adds a schema name to the map if it doesn't exist yet
 
Dictionary< string, CodeNamespace > namespaceLookup
List of generated namespaces
 
static CodeGenUtil Instance
 
abstract string Name
The name of this schema.
 
IDictionary< string, Message > Messages
List of message objects representing the different schemas defined under the 'messages' attribute
 
string Documentation
Documentation for the field, if any.
 
HashSet< string > ReservedKeywords
 
int Count
Count of schemas in the union
 
virtual CodeCompileUnit GenerateCode()
Generates code for the given protocol and schema objects
 
virtual void AddProtocol(Protocol protocol)
Adds a protocol object to generate code for
 
virtual void processEnum(Schema schema)
Creates an enum declaration
 
Type Tag
Schema type property
 
virtual void WriteCompileUnit(string outputFile)
Writes the generated compile unit into one file
 
string Mangle(string name)
Append @ to all reserved keywords that appear on the given name
 
string Namespace
Namespace of the protocol
 
virtual void WriteTypes(string outputdir)
Writes each types in each namespaces into individual files
 
Base class for all named schemas: fixed, enum, record
 
virtual void processSchemas()
Generates code for the schema objects
 
SchemaName SchemaName
Name of the schema, contains name, namespace and enclosing namespace