/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Generic; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace Avro { /// /// Provides access to custom properties (those not defined in the Avro spec) in a JSON object. /// public class PropertyMap : Dictionary { /// /// Set of reserved schema property names, any other properties not defined in this set are custom properties and can be added to this map /// private static readonly HashSet ReservedProps = new HashSet() { "type", "name", "namespace", "fields", "items", "size", "symbols", "values", "aliases", "order", "doc", "default", "logicalType" }; /// /// Parses the custom properties from the given JSON object and stores them /// into the schema's list of custom properties /// /// JSON object to prase public void Parse(JToken jtok) { JObject jo = jtok as JObject; foreach (JProperty prop in jo.Properties()) { if (ReservedProps.Contains(prop.Name)) continue; if (!ContainsKey(prop.Name)) Add(prop.Name, JsonConvert.SerializeObject(prop.Value)); } } /// /// Adds a custom property to the schema /// /// custom property name /// custom property value public void Set(string key, string value) { if (ReservedProps.Contains(key)) throw new AvroException("Can't set reserved property: " + key); string oldValue; if (TryGetValue(key, out oldValue)) { if (!oldValue.Equals(value, StringComparison.Ordinal)) { throw new AvroException("Property cannot be overwritten: " + key); } } else Add(key, value); } /// /// Writes the schema's custom properties in JSON format /// /// JSON writer public void WriteJson(JsonTextWriter writer) { foreach (KeyValuePair kp in this) { if (ReservedProps.Contains(kp.Key)) continue; writer.WritePropertyName(kp.Key); writer.WriteRawValue(kp.Value); } } /// /// Function to compare equality of two PropertyMaps /// /// other PropertyMap /// true if contents of the two maps are the same, false otherwise public override bool Equals(object obj) { if (this == obj) return true; if (obj != null && obj is PropertyMap) { var that = obj as PropertyMap; if (this.Count != that.Count) return false; foreach (KeyValuePair pair in this) { if (!that.ContainsKey(pair.Key)) return false; if (!pair.Value.Equals(that[pair.Key], StringComparison.Ordinal)) return false; } return true; } return false; } /// /// Hashcode function /// /// public override int GetHashCode() { int hash = this.Count; int index = 1; foreach (KeyValuePair pair in this) #pragma warning disable CA1307 // Specify StringComparison hash += (pair.Key.GetHashCode() + pair.Value.GetHashCode()) * index++; #pragma warning restore CA1307 // Specify StringComparison return hash; } } }