コード例 #1
0
        /// <summary>
        /// Parses the record type.
        /// </summary>
        /// <param name="record">The record.</param>
        /// <param name="parent">The parent schema.</param>
        /// <param name="namedSchemas">The named schemas.</param>
        /// <returns>
        /// Schema internal representation.
        /// </returns>
        /// <exception cref="System.Runtime.Serialization.SerializationException">Thrown when <paramref name="record"/> can not be parsed properly.</exception>
        private TypeSchema ParseRecordType(JObject record, NamedSchema parent, Dictionary <string, NamedSchema> namedSchemas)
        {
            var name       = record.RequiredProperty <string>(AvroKeywords.Name);
            var nspace     = this.GetNamespace(record, parent, name);
            var recordName = new SchemaName(name, nspace);

            var doc        = record.OptionalProperty <string>(AvroKeywords.Doc);
            var aliases    = this.GetAliases(record, recordName.Namespace);
            var attributes = new NamedEntityAttributes(recordName, aliases, doc);

            Dictionary <string, string> customAttributes = record.GetAttributesNotIn(StandardProperties.Record);
            var result = new RecordSchema(attributes, typeof(AvroRecord), customAttributes);

            namedSchemas.Add(result.FullName, result);

            List <RecordFieldSchema> fields = record.OptionalArrayProperty(
                AvroKeywords.Fields,
                (field, index) =>
            {
                if (field.Type != JTokenType.Object)
                {
                    throw new SerializationException(
                        string.Format(CultureInfo.InvariantCulture, "Property 'fields' has invalid value '{0}'.", field));
                }
                return(this.ParseRecordField(field as JObject, result, namedSchemas, index));
            });

            fields.ForEach(result.AddField);
            return(result);
        }
コード例 #2
0
        /// <summary>
        /// Parses the specified token.
        /// </summary>
        /// <param name="token">The token.</param>
        /// <param name="parent">The parent schema.</param>
        /// <param name="namedSchemas">The schemas.</param>
        /// <returns>
        /// Schema internal representation.
        /// </returns>
        /// <exception cref="System.Runtime.Serialization.SerializationException">Thrown when JSON schema type is not supported.</exception>
        private TypeSchema Parse(JToken token, NamedSchema parent, Dictionary <string, NamedSchema> namedSchemas)
        {
            if (token.Type == JTokenType.Object)
            {
                return(this.ParseJsonObject(token as JObject, parent, namedSchemas));
            }

            if (token.Type == JTokenType.String)
            {
                var t = (string)token;
                if (namedSchemas.ContainsKey(t))
                {
                    return(namedSchemas[t]);
                }

                if (parent != null && namedSchemas.ContainsKey(parent.Namespace + "." + t))
                {
                    return(namedSchemas[parent.Namespace + "." + t]);
                }

                // Primitive.
                return(this.ParsePrimitiveTypeFromString(t));
            }

            if (token.Type == JTokenType.Array)
            {
                return(this.ParseUnionType(token as JArray, parent, namedSchemas));
            }

            throw new SerializationException(
                      string.Format(CultureInfo.InvariantCulture, "Unexpected Json schema type '{0}'.", token));
        }
コード例 #3
0
        /// <summary>
        /// Parses a JSON object representing an Avro enumeration to a <see cref="EnumSchema"/>.
        /// </summary>
        /// <param name="enumeration">The JSON token that represents the enumeration.</param>
        /// <param name="parent">The parent schema.</param>
        /// <param name="namedSchemas">The named schemas.</param>
        /// <returns>
        /// Instance of <see cref="TypeSchema" /> containing IR of the enumeration.
        /// </returns>
        /// <exception cref="System.Runtime.Serialization.SerializationException">Thrown when <paramref name="enumeration"/> contains invalid symbols.</exception>
        private TypeSchema ParseEnumType(JObject enumeration, NamedSchema parent, Dictionary <string, NamedSchema> namedSchemas)
        {
            var name     = enumeration.RequiredProperty <string>(AvroKeywords.Name);
            var nspace   = this.GetNamespace(enumeration, parent, name);
            var enumName = new SchemaName(name, nspace);

            var doc        = enumeration.OptionalProperty <string>(AvroKeywords.Doc);
            var aliases    = this.GetAliases(enumeration, enumName.Namespace);
            var attributes = new NamedEntityAttributes(enumName, aliases, doc);

            List <string> symbols = enumeration.OptionalArrayProperty(
                AvroKeywords.Symbols,
                (symbol, index) =>
            {
                if (symbol.Type != JTokenType.String)
                {
                    throw new SerializationException(
                        string.Format(CultureInfo.InvariantCulture, "Expected an enum symbol of type string however the type of the symbol is '{0}'.", symbol.Type));
                }
                return((string)symbol);
            });

            Dictionary <string, string> customAttributes = enumeration.GetAttributesNotIn(StandardProperties.Enumeration);
            var result = new EnumSchema(attributes, typeof(AvroEnum), customAttributes);

            namedSchemas.Add(result.FullName, result);
            symbols.ForEach(result.AddSymbol);
            return(result);
        }
コード例 #4
0
        private static string GetCodeFileName(NamedSchema schema, string root)
        {
            var relativePath  = Path.ChangeExtension(Path.Combine(schema.FullName.Split('.')), ".cs");
            var canonicalPath = Path.Combine(root, relativePath);

            return(canonicalPath);
        }
コード例 #5
0
        /// <summary>
        /// Parses a union token.
        /// </summary>
        /// <param name="unionToken">The union token.</param>
        /// <param name="parent">The parent.</param>
        /// <param name="namedSchemas">The named schemas.</param>
        /// <returns>
        /// Schema internal representation.
        /// </returns>
        /// <exception cref="System.Runtime.Serialization.SerializationException">Thrown when union schema type is invalid.</exception>
        private TypeSchema ParseUnionType(JArray unionToken, NamedSchema parent, Dictionary <string, NamedSchema> namedSchemas)
        {
            var types   = new HashSet <string>();
            var schemas = new List <TypeSchema>();

            foreach (var typeAlternative in unionToken.Children())
            {
                var schema = this.Parse(typeAlternative, parent, namedSchemas);
                if (schema.Type == AvroType.Union)
                {
                    throw new SerializationException(
                              string.Format(CultureInfo.InvariantCulture, "Union schemas cannot be nested:'{0}'.", unionToken));
                }

                if (types.Contains(schema.Name))
                {
                    throw new SerializationException(
                              string.Format(CultureInfo.InvariantCulture, "Unions cannot contains schemas of the same type: '{0}'.", schema.Name));
                }

                types.Add(schema.Name);
                schemas.Add(schema);
            }

            return(new UnionSchema(schemas, typeof(object)));
        }
コード例 #6
0
        private static MemberDeclarationSyntax CreateCode(NamedSchema schema, IDictionary <string, string> nsMap)
        {
            var schemaTypeName = schema.GetType().Name;

            var ns  = schema.Namespace;
            var trn = nsMap.OrderByDescending(r => r.Key).FirstOrDefault(r => ns != null && ns.StartsWith(r.Key));

            if (!string.IsNullOrEmpty(trn.Key))
            {
                ns = $"{trn.Value}{ns.Substring(trn.Key.Length)}";
            }

            switch (schemaTypeName)
            {
            case nameof(FixedSchema):
                return(CreateFixedCode(schema as FixedSchema, ns));

            case nameof(EnumSchema):
                return(CreateEnumCode(schema as EnumSchema, ns));

            case nameof(RecordSchema):
                return(CreateRecordCode(schema as RecordSchema, ns, false));

            case nameof(ErrorSchema):
                return(CreateRecordCode(schema as RecordSchema, ns, true));

            default:
                throw new CodeGenException($"Unsupported Schema: {schemaTypeName}");
            }
        }
コード例 #7
0
        private string GetNamespace(JObject type, NamedSchema parentSchema, string name)
        {
            var nspace = type.OptionalProperty <string>(AvroKeywords.Namespace);

            if (string.IsNullOrEmpty(nspace) && !name.Contains(".") && parentSchema != null)
            {
                nspace = parentSchema.Namespace;
            }
            return(nspace);
        }
コード例 #8
0
ファイル: EnumCache.cs プロジェクト: cunchy0/avro-1
        /// <summary>
        /// Lookup an entry in the cache - based on the schema fullname
        /// </summary>
        /// <param name="schema"></param>
        /// <returns></returns>
        public static Type GetEnumeration(NamedSchema schema)
        {
            Type t;

            if (!_nameEnumMap.TryGetValue(schema.Fullname, out t))
            {
                throw new AvroException($"Couldnt find enumeration for avro fullname: {schema.Fullname}");
            }

            return(t);
        }
コード例 #9
0
        public static string GetCode(NamedSchema schema)
        {
            var codeGen = new CodeGen();

            codeGen.AddSchema(schema);
            var codeBuilder = new StringBuilder();

            using (var codeWriter = new StringWriter(codeBuilder))
                codeGen.WriteCode(codeWriter);
            return(codeBuilder.ToString());
        }
コード例 #10
0
        /// <summary>
        /// Parses the JSON object.
        /// </summary>
        /// <param name="token">The object.</param>
        /// <param name="parent">The parent schema.</param>
        /// <param name="namedSchemas">The schemas.</param>
        /// <returns>
        /// Schema internal representation.
        /// </returns>
        /// <exception cref="System.Runtime.Serialization.SerializationException">Thrown when JSON schema type is invalid.</exception>
        private TypeSchema ParseJsonObject(JObject token, NamedSchema parent, Dictionary <string, NamedSchema> namedSchemas)
        {
            JToken tokenType = token[AvroKeywords.Type];

            if (tokenType.Type == JTokenType.String)
            {
                var typeString = token.RequiredProperty <string>(AvroKeywords.Type);
                Enum.TryParse(typeString, true, out AvroType type);

                var logicalType = token.OptionalProperty <string>(AvroKeywords.LogicalType);
                if (logicalType != null)
                {
                    return(this.ParseLogicalType(token, parent, namedSchemas, logicalType));
                }

                switch (type)
                {
                case AvroType.Record:
                    return(this.ParseRecordType(token, parent, namedSchemas));

                case AvroType.Enum:
                    return(this.ParseEnumType(token, parent, namedSchemas));

                case AvroType.Array:
                    return(this.ParseArrayType(token, parent, namedSchemas));

                case AvroType.Map:
                    return(this.ParseMapType(token, parent, namedSchemas));

                case AvroType.Fixed:
                    return(this.ParseFixedType(token, parent));

                default:
                {
                    if (PrimitiveRuntimeType.ContainsKey(type.ToString()))
                    {
                        return(this.ParsePrimitiveTypeFromObject(token));
                    }

                    throw new SerializationException(
                              string.Format(CultureInfo.InvariantCulture, "Invalid type specified: '{0}'.", type));
                }
                }
            }

            if (tokenType.Type == JTokenType.Array)
            {
                return(this.ParseUnionType(tokenType as JArray, parent, namedSchemas));
            }

            throw new SerializationException(
                      string.Format(CultureInfo.InvariantCulture, "Invalid type specified: '{0}'.", tokenType));
        }
コード例 #11
0
        /// <summary>
        /// Parses a JSON object representing an Avro array.
        /// </summary>
        /// <param name="array">JSON representing the array.</param>
        /// <param name="parent">The parent.</param>
        /// <param name="namedSchemas">The named schemas.</param>
        /// <returns>
        /// A corresponding schema.
        /// </returns>
        /// <exception cref="System.Runtime.Serialization.SerializationException">Thrown when no 'items' property is found in <paramref name="array" />.</exception>
        private TypeSchema ParseArrayType(JObject array, NamedSchema parent, Dictionary <string, NamedSchema> namedSchemas)
        {
            var itemType = array[AvroKeywords.Items];

            if (itemType == null)
            {
                throw new SerializationException(
                          string.Format(CultureInfo.InvariantCulture, "Property 'items' cannot be found inside the array '{0}'.", array));
            }

            var elementSchema = this.Parse(itemType, parent, namedSchemas);

            return(new ArraySchema(elementSchema, typeof(Array)));
        }
コード例 #12
0
        /// <summary>
        /// Parses a JSON object representing an Avro map.
        /// </summary>
        /// <param name="map">JSON representing the map.</param>
        /// <param name="parent">The parent.</param>
        /// <param name="namedSchemas">The named schemas.</param>
        /// <returns>
        /// A corresponding schema.
        /// </returns>
        /// <exception cref="System.Runtime.Serialization.SerializationException">Thrown when 'values' property is not found in <paramref name="map" />.</exception>
        private TypeSchema ParseMapType(JObject map, NamedSchema parent, Dictionary <string, NamedSchema> namedSchemas)
        {
            var valueType = map[AvroKeywords.Values];

            if (valueType == null)
            {
                throw new SerializationException(
                          string.Format(CultureInfo.InvariantCulture, "Property 'values' cannot be found inside the map '{0}'.", map));
            }

            var valueSchema = this.Parse(valueType, parent, namedSchemas);

            return(new MapSchema(new StringSchema(), valueSchema, typeof(Dictionary <string, object>)));
        }
コード例 #13
0
        private TypeSchema ParseLogicalType(JObject token, NamedSchema parent, Dictionary <string, NamedSchema> namedSchemas, string logicalType)
        {
            TypeSchema result;

            switch (logicalType)
            {
            case LogicalTypeSchema.LogicalTypeEnum.Uuid:
                result = new UuidSchema();
                break;

            case LogicalTypeSchema.LogicalTypeEnum.Decimal:
                var scale     = token.OptionalProperty <int>(nameof(DecimalSchema.Scale).ToLower());
                var precision = token.RequiredProperty <int>(nameof(DecimalSchema.Precision).ToLower());
                result = new DecimalSchema(typeof(decimal), precision, scale);
                break;

            case LogicalTypeSchema.LogicalTypeEnum.Duration:
                result = new DurationSchema();
                break;

            case LogicalTypeSchema.LogicalTypeEnum.TimestampMilliseconds:
                result = new TimestampMillisecondsSchema();
                break;

            case LogicalTypeSchema.LogicalTypeEnum.TimestampMicroseconds:
                result = new TimestampMicrosecondsSchema();
                break;

            case LogicalTypeSchema.LogicalTypeEnum.TimeMilliseconds:
                result = new TimeMillisecondsSchema();
                break;

            case LogicalTypeSchema.LogicalTypeEnum.TimeMicrosecond:
                result = new TimeMicrosecondsSchema();
                break;

            case LogicalTypeSchema.LogicalTypeEnum.Date:
                result = new DateSchema();
                break;

            default:
                throw new SerializationException(
                          string.Format(CultureInfo.InvariantCulture, "Unknown LogicalType schema :'{0}'.", logicalType));
            }

            return(result);
        }
コード例 #14
0
        /// <summary>
        /// Gets the name of the property used to disambiguate a union.
        /// </summary>
        /// <param name="schema">
        /// A child of the union schema.
        /// </param>
        /// <returns>
        /// If <paramref name="schema" /> is a <see cref="NamedSchema" />, the fully-qualified
        /// name; the type name otherwise.
        /// </returns>
        protected virtual string GetSchemaName(Schema schema)
        {
            return(schema switch
            {
                NamedSchema namedSchema => namedSchema.FullName,

                ArraySchema => JsonSchemaToken.Array,
                BooleanSchema => JsonSchemaToken.Boolean,
                BytesSchema => JsonSchemaToken.Bytes,
                DoubleSchema => JsonSchemaToken.Double,
                FloatSchema => JsonSchemaToken.Float,
                IntSchema => JsonSchemaToken.Int,
                LongSchema => JsonSchemaToken.Long,
                MapSchema => JsonSchemaToken.Map,
                StringSchema => JsonSchemaToken.String,

                _ => throw new UnsupportedSchemaException(schema),
            });
コード例 #15
0
        /// <summary>
        /// Parses the record field.
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="parent">The parent schema.</param>
        /// <param name="namedSchemas">The named schemas.</param>
        /// <param name="position">The position.</param>
        /// <returns>
        /// Schema internal representation.
        /// </returns>
        /// <exception cref="System.Runtime.Serialization.SerializationException">Thrown when <paramref name="field"/> is not valid or when sort order is not valid.</exception>
        private RecordFieldSchema ParseRecordField(JObject field, NamedSchema parent, Dictionary <string, NamedSchema> namedSchemas, int position)
        {
            var name      = field.RequiredProperty <string>(AvroKeywords.Name);
            var doc       = field.OptionalProperty <string>(AvroKeywords.Doc);
            var order     = field.OptionalProperty <string>(AvroKeywords.Order);
            var aliases   = this.GetAliases(field, parent.FullName);
            var fieldType = field[AvroKeywords.Type];

            if (fieldType == null)
            {
                throw new SerializationException(
                          string.Format(CultureInfo.InvariantCulture, "Record field schema '{0}' has no type.", field));
            }

            TypeSchema type            = this.Parse(fieldType, parent, namedSchemas);
            object     defaultValue    = null;
            bool       hasDefaultValue = field[AvroKeywords.Default] != null;

            if (hasDefaultValue)
            {
                var objectParser = new JsonObjectParser();
                defaultValue = objectParser.Parse(type, field[AvroKeywords.Default].ToString());
            }

            var orderValue = SortOrder.Ascending;

            if (!string.IsNullOrEmpty(order))
            {
                if (!SortValue.ContainsKey(order.ToUpperInvariant()))
                {
                    throw new SerializationException(
                              string.Format(CultureInfo.InvariantCulture, "Invalid sort order of the field '{0}'.", order));
                }
                orderValue = SortValue[order.ToUpperInvariant()];
            }

            var fieldName  = new SchemaName(name);
            var attributes = new NamedEntityAttributes(fieldName, aliases, doc);

            return(new RecordFieldSchema(attributes, type, orderValue, hasDefaultValue, defaultValue, null, position));
        }
コード例 #16
0
        private FixedSchema ParseFixedType(JObject type, NamedSchema parent)
        {
            var name      = type.RequiredProperty <string>(AvroKeywords.Name);
            var nspace    = this.GetNamespace(type, parent, name);
            var fixedName = new SchemaName(name, nspace);

            var size = type.RequiredProperty <int>(AvroKeywords.Size);

            if (size <= 0)
            {
                throw new SerializationException(
                          string.Format(CultureInfo.InvariantCulture, "Only positive size of fixed values allowed: '{0}'.", size));
            }

            var aliases    = this.GetAliases(type, fixedName.Namespace);
            var attributes = new NamedEntityAttributes(fixedName, aliases, string.Empty);

            var customAttributes = type.GetAttributesNotIn(StandardProperties.Record);
            var result           = new FixedSchema(attributes, size, typeof(byte[]), customAttributes);

            return(result);
        }
コード例 #17
0
 public ParameterSchema(string name, NamedSchema type)
 {
     Name = name;
     Type = type;
 }
コード例 #18
0
        public static Assembly Compile(string assemblyName, NamedSchema schema, out XmlDocument xmlDocumentation)
        {
            var code = GetCode(schema);

            return(Compile(assemblyName, code, out xmlDocumentation));
        }
コード例 #19
0
        /// <summary>
        /// Recursively search the given schema for named schemas and adds them to the given container
        /// </summary>
        /// <param name="schema">schema object to search</param>
        /// <param name="names">list of named schemas</param>
        protected virtual void addName(Schema schema, SchemaNames names)
        {
            NamedSchema ns = schema as NamedSchema;

            if (null != ns)
            {
                if (names.Contains(ns.SchemaName))
                {
                    return;
                }
            }

            switch (schema.Tag)
            {
            case Schema.Type.Null:
            case Schema.Type.Boolean:
            case Schema.Type.Int:
            case Schema.Type.Long:
            case Schema.Type.Float:
            case Schema.Type.Double:
            case Schema.Type.Bytes:
            case Schema.Type.String:
                break;

            case Schema.Type.Enumeration:
            case Schema.Type.Fixed:
                names.Add(ns);
                break;

            case Schema.Type.Record:
            case Schema.Type.Error:
                var rs = schema as RecordSchema;
                names.Add(rs);
                foreach (Field field in rs.Fields)
                {
                    addName(field.Schema, names);
                }
                break;

            case Schema.Type.Array:
                var asc = schema as ArraySchema;
                addName(asc.ItemSchema, names);
                break;

            case Schema.Type.Map:
                var ms = schema as MapSchema;
                addName(ms.ValueSchema, names);
                break;

            case Schema.Type.Union:
                var us = schema as UnionSchema;
                foreach (Schema usc in us.Schemas)
                {
                    addName(usc, names);
                }
                break;

            default:
                throw new CodeGenException("Unable to add name for " + schema.Name + " type " + schema.Tag);
            }
        }
コード例 #20
0
        private FixedSchema TryBuildFixedSchema(Type memberType, MemberInfo memberInfo, NamedSchema parentSchema)
        {
            var result = memberInfo.GetCustomAttributes(false).OfType <AvroFixedAttribute>().FirstOrDefault();

            if (result == null)
            {
                return(null);
            }

            if (memberType != typeof(byte[]))
            {
                throw new SerializationException(
                          string.Format(CultureInfo.InvariantCulture, "'{0}' can be set only to members of type byte[].", typeof(AvroFixedAttribute)));
            }

            var schemaNamespace = string.IsNullOrEmpty(result.Namespace) && !result.Name.Contains(".") && parentSchema != null
                                      ? parentSchema.Namespace
                                      : result.Namespace;

            return(new FixedSchema(
                       new NamedEntityAttributes(new SchemaName(result.Name, schemaNamespace), new List <string>(), string.Empty),
                       result.Size,
                       memberType));
        }
コード例 #21
0
ファイル: EnumCache.cs プロジェクト: cunchy0/avro-1
 /// <summary>
 /// Add and entry to the cache
 /// </summary>
 /// <param name="schema"></param>
 /// <param name="dotnetEnum"></param>
 public static void AddEnumNameMapItem(NamedSchema schema, Type dotnetEnum)
 {
     _nameEnumMap.TryAdd(schema.Fullname, dotnetEnum);
 }