blob: 3804d1584a9bfed44d3ea7d01f7f3373e7958d67 [file] [log] [blame]
/**
* 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
*
* http://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 System.Linq;
using System.Text;
using Avro;
namespace Avro.Generic
{
/// <summary>
/// The default type used by GenericReader and GenericWriter for RecordSchema.
/// </summary>
public class GenericRecord
{
public RecordSchema Schema { get; private set; }
private IDictionary<string, object> contents = new Dictionary<string, object>();
public GenericRecord(RecordSchema schema)
{
this.Schema = schema;
}
public object this[string fieldName]
{
get { return contents[fieldName]; }
}
public void Add(string fieldName, object fieldValue)
{
if (Schema.Contains(fieldName))
{
// TODO: Use a matcher to verify that object has the right type for the field.
//contents.Add(fieldName, fieldValue);
contents[fieldName] = fieldValue;
return;
}
throw new AvroException("No such field: " + fieldName);
}
public bool TryGetValue(string fieldName, out object result)
{
return contents.TryGetValue(fieldName, out result);
}
public override bool Equals(object obj)
{
if (this == obj) return true;
if (obj != null && obj is GenericRecord)
{
GenericRecord other = obj as GenericRecord;
return Schema.Equals(other.Schema) && areEqual(contents, other.contents);
}
return false;
}
private static bool areEqual(IDictionary<string, object> d1, IDictionary<string, object> d2)
{
if (d1.Count == d2.Count)
{
foreach (KeyValuePair<string, object> kv in d1)
{
object o;
if (!d2.TryGetValue(kv.Key, out o)) return false;
if (!areEqual(o, kv.Value)) return false;
}
return true;
}
return false;
}
private static bool areEqual(object o1, object o2)
{
if (o1 == null) return o2 == null;
if (o2 == null) return false;
if (o1 is Array)
{
if (!(o2 is Array)) return false;
return areEqual(o1 as Array, o1 as Array);
}
else if (o1 is IDictionary<string, object>)
{
if (!(o2 is IDictionary<string, object>)) return false;
return areEqual(o1 as IDictionary<string, object>, o1 as IDictionary<string, object>);
}
return o1.Equals(o2);
}
private static bool areEqual(Array a1, Array a2)
{
if (a1.Length != a2.Length) return false;
for (int i = 0; i < a1.Length; i++)
{
if (!areEqual(a1.GetValue(i), a2.GetValue(i))) return false;
}
return true;
}
public override int GetHashCode()
{
return 31 * contents.GetHashCode()/* + 29 * Schema.GetHashCode()*/;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append("Schema: ");
sb.Append(Schema);
sb.Append(", contents: ");
sb.Append("{ ");
foreach (KeyValuePair<string, object> kv in contents)
{
sb.Append(kv.Key);
sb.Append(": ");
sb.Append(kv.Value);
sb.Append(", ");
}
sb.Append("}");
return sb.ToString();
}
}
}