You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by cu...@apache.org on 2011/03/31 23:16:49 UTC

svn commit: r1087439 [3/6] - in /avro/trunk: ./ lang/csharp/ lang/csharp/lib/ lang/csharp/lib/main/ lang/csharp/lib/test/ lang/csharp/src/ lang/csharp/src/apache/ lang/csharp/src/apache/codegen/ lang/csharp/src/apache/codegen/Properties/ lang/csharp/sr...

Added: avro/trunk/lang/csharp/src/apache/main/IO/BinaryEncoder.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/IO/BinaryEncoder.cs?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/IO/BinaryEncoder.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/IO/BinaryEncoder.cs Thu Mar 31 21:16:28 2011
@@ -0,0 +1,190 @@
+/**
+ * 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.IO;
+
+namespace Avro.IO
+{
+    /// <summary>
+    /// Write leaf values.
+    /// </summary>
+    public class BinaryEncoder : Encoder
+    {
+        private readonly Stream Stream;
+
+        public BinaryEncoder() : this(null)
+        {
+        }
+
+        public BinaryEncoder(Stream stream)
+        {
+            this.Stream = stream;
+        }
+
+        /// <summary>
+        /// null is written as zero bytes
+        /// </summary>
+        public void WriteNull()
+        {
+        }
+        
+        /// <summary>
+        /// true is written as 1 and false 0.
+        /// </summary>
+        /// <param name="b">Boolean value to write</param>
+        public void WriteBoolean(bool b)
+        {
+            writeByte((byte)(b ? 1 : 0));
+        }
+
+        /// <summary>
+        /// int and long values are written using variable-length, zig-zag coding.
+        /// </summary>
+        /// <param name="datum"></param>
+        public void WriteInt(int value)
+        {
+            WriteLong(value);
+        }
+        /// <summary>
+        /// int and long values are written using variable-length, zig-zag coding.
+        /// </summary>
+        /// <param name="datum"></param>
+        public void WriteLong(long value)
+        {
+            ulong n = (ulong)((value << 1) ^ (value >> 63));
+            while ((n & ~0x7FUL) != 0)
+            {
+                writeByte((byte)((n & 0x7f) | 0x80));
+                n >>= 7;
+            }
+            writeByte((byte)n);
+        }
+
+        /// <summary>
+        /// A float is written as 4 bytes.
+        /// The float is converted into a 32-bit integer using a method equivalent to
+        /// Java's floatToIntBits and then encoded in little-endian format.
+        /// </summary>
+        /// <param name="value"></param>
+        public void WriteFloat(float value)
+        {
+            byte[] buffer = BitConverter.GetBytes(value);
+            if (!BitConverter.IsLittleEndian) Array.Reverse(buffer);
+            writeBytes(buffer);
+        }
+        /// <summary>
+        ///A double is written as 8 bytes.
+        ///The double is converted into a 64-bit integer using a method equivalent to
+        ///Java's doubleToLongBits and then encoded in little-endian format.
+        /// </summary>
+        /// <param name="value"></param>
+        public void WriteDouble(double value)
+        {
+            long bits = BitConverter.DoubleToInt64Bits(value);
+            
+            writeByte((byte)((bits) & 0xFF));
+            writeByte((byte)((bits >> 8) & 0xFF));
+            writeByte((byte)((bits >> 16) & 0xFF));
+            writeByte((byte)((bits >> 24) & 0xFF));
+            writeByte((byte)((bits >> 32) & 0xFF));
+            writeByte((byte)((bits >> 40) & 0xFF));
+            writeByte((byte)((bits >> 48) & 0xFF));
+            writeByte((byte)((bits >> 56) & 0xFF));
+            
+        }
+
+        /// <summary>
+        /// Bytes are encoded as a long followed by that many bytes of data.
+        /// </summary>
+        /// <param name="value"></param>
+        /// 
+        public void WriteBytes(byte[] value)
+        {
+            WriteLong(value.Length);
+            writeBytes(value);
+        }
+
+        /// <summary>
+        /// A string is encoded as a long followed by
+        /// that many bytes of UTF-8 encoded character data.
+        /// </summary>
+        /// <param name="value"></param>
+        public void WriteString(string value)
+        {
+            WriteBytes(System.Text.Encoding.UTF8.GetBytes(value));
+        }
+
+        public void WriteEnum(int value)
+        {
+            WriteLong(value);
+        }
+
+        public void StartItem()
+        {
+        }
+
+        public void SetItemCount(long value)
+        {
+            if (value > 0) WriteLong(value);
+        }
+
+        public void WriteArrayStart()
+        {
+        }
+
+        public void WriteArrayEnd()
+        {
+            WriteLong(0);
+        }
+
+        public void WriteMapStart()
+        {
+        }
+
+        public void WriteMapEnd()
+        {
+            WriteLong(0);
+        }
+
+        public void WriteUnionIndex(int value)
+        {
+            WriteLong(value);
+        }
+
+        public void WriteFixed(byte[] data)
+        {
+            WriteFixed(data, 0, data.Length);
+        }
+
+        public void WriteFixed(byte[] data, int start, int len)
+        {
+            Stream.Write(data, start, len);
+        }
+
+        private void writeBytes(byte[] bytes)
+        {
+            Stream.Write(bytes, 0, bytes.Length);
+        }
+
+        private void writeByte(byte b)
+        {
+            Stream.WriteByte(b);
+        }
+    }
+}

Added: avro/trunk/lang/csharp/src/apache/main/IO/Decoder.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/IO/Decoder.cs?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/IO/Decoder.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/IO/Decoder.cs Thu Mar 31 21:16:28 2011
@@ -0,0 +1,188 @@
+/**
+ * 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.IO;
+
+namespace Avro.IO
+{
+    /// <summary>
+    /// Decoder is used to decode Avro data on a stream. There are methods to read the Avro types on the stream. There are also
+    /// methods to skip items, which are usually more efficient than reading, on the stream.
+    /// </summary>
+    public interface Decoder
+    {
+        /// <summary>
+        /// Reads a null Avro type.
+        /// </summary>
+        void ReadNull();
+
+        /// <summary>
+        /// Read a boolean Avro type
+        /// </summary>
+        /// <returns>The boolean just read</returns>
+        bool ReadBoolean();
+
+        /// <summary>
+        /// Reads an int Avro type.
+        /// </summary>
+        /// <returns>The int just read</returns>
+        int ReadInt();
+
+        /// <summary>
+        /// Reads a long Avro type.
+        /// </summary>
+        /// <returns>The long just read</returns>
+        long ReadLong();
+
+        /// <summary>
+        /// Reads a float Avro type
+        /// </summary>
+        /// <returns>The float just read</returns>
+        float ReadFloat();
+
+        /// <summary>
+        /// Reads a double Avro type
+        /// </summary>
+        /// <returns>The double just read</returns>
+        double ReadDouble();
+
+        /// <summary>
+        /// Reads the bytes Avro type
+        /// </summary>
+        /// <returns>The bytes just read</returns>
+        byte[] ReadBytes();
+
+        /// <summary>
+        /// Reads a string Avro type
+        /// </summary>
+        /// <returns>The string just read</returns>
+        string ReadString();
+
+        /// <summary>
+        /// Reads an enum AvroType
+        /// </summary>
+        /// <returns>The enum just read</returns>
+        int ReadEnum();
+
+        /// <summary>
+        /// Starts reading the array Avro type. This, together with ReadArrayNext() is used to read the
+        /// items from Avro array. This returns the number of entries in the initial chunk. After consuming
+        /// the chunk, the client should call ReadArrayNext() to get the number of entries in the next
+        /// chunk. The client should repeat the procedure until there are no more entries in the array.
+        /// 
+        /// for (int n = decoder.ReadArrayStart(); n > 0; n = decoder.ReadArrayNext())
+        /// {
+        ///     // Read one array entry.
+        /// }
+        /// </summary>
+        /// <returns>The number of entries in the initial chunk, 0 if the array is empty.</returns>
+        long ReadArrayStart();
+
+        /// <summary>
+        /// See ReadArrayStart().
+        /// </summary>
+        /// <returns>The number of array entries in the next chunk, 0 if there are no more entries.</returns>
+        long ReadArrayNext();
+
+        /// <summary>
+        /// Starts reading the map Avro type. This, together with ReadMapNext() is used to read the
+        /// entries from Avro map. This returns the number of entries in the initial chunk. After consuming
+        /// the chunk, the client should call ReadMapNext() to get the number of entriess in the next
+        /// chunk. The client should repeat the procedure until there are no more entries in the array.
+        /// for (int n = decoder.ReadMapStart(); n > 0; n = decoder.ReadMapNext())
+        /// {
+        ///     // Read one map entry.
+        /// }
+        /// </summary>
+        /// <returns>The number of entries in the initial chunk, 0 if the map is empty.</returns>
+        long ReadMapStart();
+
+        /// <summary>
+        /// See ReadMapStart().
+        /// </summary>
+        /// <returns>The number of map entries in the next chunk, 0 if there are no more entries.</returns>
+        long ReadMapNext();
+
+        /// <summary>
+        /// Reads the index, which determines the type in an union Avro type.
+        /// </summary>
+        /// <returns>The index of the type within the union.</returns>
+        int ReadUnionIndex();
+
+        /// <summary>
+        /// A convenience method for ReadFixed(buffer, 0, buffer.Length);
+        /// </summary>
+        /// <param name="buffer"> The buffer to read into.</param>
+        void ReadFixed(byte[] buffer);
+
+        /// <summary>
+        /// Read a Fixed Avro type of length.
+        /// </summary>
+        /// <param name="buffer">Buffer to read into</param>
+        /// <param name="start">Starting position of buffer to read into</param>
+        /// <param name="length">Number of bytes to read</param>
+        void ReadFixed(byte[] buffer, int start, int length);
+
+        /// <summary>
+        /// Skips a null Avro type on the stream.
+        /// </summary>
+        void SkipNull();
+
+        /// <summary>
+        ///  Skips a boolean Avro type on the stream.
+        /// </summary>
+        void SkipBoolean();
+
+        /// <summary>
+        ///  Skips a int Avro type on the stream.
+        /// </summary>
+        void SkipInt();
+        
+        /// <summary>
+        ///  Skips a long Avro type on the stream.
+        /// </summary>
+        void SkipLong();
+
+        /// <summary>
+        /// Skips a float Avro type on the stream.
+        /// </summary>
+        void SkipFloat();
+
+        /// <summary>
+        /// Skips a double Avro type on the stream.
+        /// </summary>
+        void SkipDouble();
+
+        /// <summary>
+        /// Skips a bytes Avro type on the stream.
+        /// </summary>
+        void SkipBytes();
+
+        /// <summary>
+        /// Skips a string Avro type on the stream.
+        /// </summary>
+        void SkipString();
+
+        void SkipEnum();
+
+        void SkipUnionIndex();
+
+        void SkipFixed(int len);
+    }
+
+}

Added: avro/trunk/lang/csharp/src/apache/main/IO/Encoder.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/IO/Encoder.cs?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/IO/Encoder.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/IO/Encoder.cs Thu Mar 31 21:16:28 2011
@@ -0,0 +1,50 @@
+/**
+ * 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.IO;
+
+namespace Avro.IO
+{
+    public interface Encoder
+    {
+        void WriteNull();
+        void WriteBoolean(bool value);
+        void WriteInt(int value);
+        void WriteLong(long value);
+        void WriteFloat(float value);
+        void WriteDouble(double value);
+        void WriteBytes(byte[] value);
+        void WriteString(string value);
+
+        void WriteEnum(int value);
+
+        void SetItemCount(long value);
+        void StartItem();
+        
+        void WriteArrayStart();
+        void WriteArrayEnd();
+
+        void WriteMapStart();
+        void WriteMapEnd();
+
+        void WriteUnionIndex(int value);
+        void WriteFixed(byte[] data);
+        void WriteFixed(byte[] data, int start, int len);
+    }
+}

Added: avro/trunk/lang/csharp/src/apache/main/IO/Resolver.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/IO/Resolver.cs?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/IO/Resolver.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/IO/Resolver.cs Thu Mar 31 21:16:28 2011
@@ -0,0 +1,166 @@
+/**
+ * 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 Newtonsoft.Json.Linq;
+using Newtonsoft.Json;
+
+namespace Avro.IO
+{
+    static class Resolver
+    {
+        /// <summary>
+        /// Reads the passed JToken default value field and writes it in the specified encoder 
+        /// </summary>
+        /// <param name="enc">encoder to use for writing</param>
+        /// <param name="schema">schema object for the current field</param>
+        /// <param name="jtok">default value as JToken</param>
+        public static void EncodeDefaultValue(Encoder enc, Schema schema, JToken jtok)
+        {
+            if (null == jtok) return;
+
+            switch (schema.Tag)
+            {
+                case Schema.Type.Boolean:
+                    if (jtok.Type != JTokenType.Boolean)
+                        throw new AvroException("Default boolean value " + jtok.ToString() + " is invalid, expected is json boolean.");
+                    enc.WriteBoolean((bool)jtok);
+                    break;
+
+                case Schema.Type.Int:
+                    if (jtok.Type != JTokenType.Integer)
+                        throw new AvroException("Default int value " + jtok.ToString() + " is invalid, expected is json integer.");
+                    enc.WriteInt(Convert.ToInt32((int)jtok));
+                    break;
+
+                case Schema.Type.Long:
+                    if (jtok.Type != JTokenType.Integer)
+                        throw new AvroException("Default long value " + jtok.ToString() + " is invalid, expected is json integer.");
+                    enc.WriteLong(Convert.ToInt64((long)jtok));
+                    break;
+
+                case Schema.Type.Float:
+                    if (jtok.Type != JTokenType.Float)
+                        throw new AvroException("Default float value " + jtok.ToString() + " is invalid, expected is json number.");
+                    enc.WriteFloat((float)jtok);
+                    break;
+
+                case Schema.Type.Double:
+                    if (jtok.Type == JTokenType.Integer)
+                        enc.WriteDouble(Convert.ToDouble((int)jtok));
+                    else if (jtok.Type == JTokenType.Float)
+                        enc.WriteDouble(Convert.ToDouble((float)jtok));
+                    else
+                        throw new AvroException("Default double value " + jtok.ToString() + " is invalid, expected is json number.");
+
+                    break;
+
+                case Schema.Type.Bytes:
+                    if (jtok.Type != JTokenType.String)
+                        throw new AvroException("Default bytes value " + jtok.ToString() + " is invalid, expected is json string.");
+                    var en = System.Text.Encoding.GetEncoding("iso-8859-1");
+                    enc.WriteBytes(en.GetBytes((string)jtok));
+                    break;
+
+                case Schema.Type.Fixed:
+                    if (jtok.Type != JTokenType.String)
+                        throw new AvroException("Default fixed value " + jtok.ToString() + " is invalid, expected is json string.");
+                    en = System.Text.Encoding.GetEncoding("iso-8859-1");
+                    int len = (schema as FixedSchema).Size;
+                    byte[] bb = en.GetBytes((string)jtok);
+                    if (bb.Length != len)
+                        throw new AvroException("Default fixed value " + jtok.ToString() + " is not of expected length " + len);
+                    enc.WriteFixed(bb);
+                    break;
+
+                case Schema.Type.String:
+                    if (jtok.Type != JTokenType.String)
+                        throw new AvroException("Default string value " + jtok.ToString() + " is invalid, expected is json string.");
+                    enc.WriteString((string)jtok);
+                    break;
+
+                case Schema.Type.Enumeration:
+                    if (jtok.Type != JTokenType.String)
+                        throw new AvroException("Default enum value " + jtok.ToString() + " is invalid, expected is json string.");
+                    enc.WriteEnum((schema as EnumSchema).Ordinal((string)jtok));
+                    break;
+
+                case Schema.Type.Null:
+                    if (jtok.Type != JTokenType.Null)
+                        throw new AvroException("Default null value " + jtok.ToString() + " is invalid, expected is json null.");
+                    enc.WriteNull();
+                    break;
+
+                case Schema.Type.Array:
+                    if (jtok.Type != JTokenType.Array)
+                        throw new AvroException("Default array value " + jtok.ToString() + " is invalid, expected is json array.");
+                    JArray jarr = jtok as JArray;
+                    enc.WriteArrayStart();
+                    enc.SetItemCount(jarr.Count);
+                    foreach (JToken jitem in jarr)
+                    {
+                        enc.StartItem();
+                        EncodeDefaultValue(enc, (schema as ArraySchema).ItemSchema, jitem);
+                    }
+                    enc.WriteArrayEnd();
+                    break;
+
+                case Schema.Type.Record:
+                case Schema.Type.Error:
+                    if (jtok.Type != JTokenType.Object)
+                        throw new AvroException("Default record value " + jtok.ToString() + " is invalid, expected is json object.");
+                    RecordSchema rcs = schema as RecordSchema;
+                    JObject jo = jtok as JObject;
+                    foreach (Field field in rcs)
+                    {
+                        JToken val = jo[field.Name];
+                        if (null == val)
+                            val = field.DefaultValue;
+                        if (null == val)
+                            throw new AvroException("No default value for field " + field.Name);
+
+                        EncodeDefaultValue(enc, field.Schema, val);
+                    }
+                    break;
+
+                case Schema.Type.Map:
+                    if (jtok.Type != JTokenType.Object)
+                        throw new AvroException("Default map value " + jtok.ToString() + " is invalid, expected is json object.");
+                    jo = jtok as JObject;
+                    enc.WriteMapStart();
+                    enc.SetItemCount(jo.Count);
+                    foreach (KeyValuePair<string, JToken> jp in jo)
+                    {
+                        enc.StartItem();
+                        enc.WriteString(jp.Key);
+                        EncodeDefaultValue(enc, (schema as MapSchema).ValueSchema, jp.Value);
+                    }
+                    enc.WriteMapEnd();
+                    break;
+
+                case Schema.Type.Union:
+                    enc.WriteUnionIndex(0);
+                    EncodeDefaultValue(enc, (schema as UnionSchema).Schemas[0], jtok);
+                    break;
+
+                default:
+                    throw new AvroException("Unsupported schema type " + schema.Tag);
+            }
+        }
+    }
+}

Added: avro/trunk/lang/csharp/src/apache/main/Properties/AssemblyInfo.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Properties/AssemblyInfo.cs?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Properties/AssemblyInfo.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Properties/AssemblyInfo.cs Thu Mar 31 21:16:28 2011
@@ -0,0 +1,53 @@
+/**
+ * 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.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Avro")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache")]
+[assembly: AssemblyProduct("Avro")]
+[assembly: AssemblyCopyright("Copyright © Apache 2010")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("6984e56e-b67f-44c1-9aaf-0483c7589642")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("0.9.0.0")]
+[assembly: AssemblyFileVersion("0.9.0.0")]

Added: avro/trunk/lang/csharp/src/apache/main/Properties/Settings.Designer.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Properties/Settings.Designer.cs?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Properties/Settings.Designer.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Properties/Settings.Designer.cs Thu Mar 31 21:16:28 2011
@@ -0,0 +1,44 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.1
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+/**
+ * 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.
+ */
+
+namespace Avro.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+    }
+}

Added: avro/trunk/lang/csharp/src/apache/main/Protocol/Message.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Protocol/Message.cs?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Protocol/Message.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Protocol/Message.cs Thu Mar 31 21:16:28 2011
@@ -0,0 +1,145 @@
+/**
+ * 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.Text;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json;
+
+namespace Avro
+{
+    public class Message
+    {
+        /// <summary>
+        /// Name of the message
+        /// </summary>
+        public string Name { get; set; }
+
+        /// <summary>
+        /// Documentation for the message
+        /// </summary>
+        public string Doc { get; set; }
+
+        /// <summary>
+        /// Anonymous record for the list of parameters for the request fields
+        /// </summary>
+        public RecordSchema Request { get; set; }
+
+        /// <summary>
+        /// Schema object for the 'response' attribute
+        /// </summary>
+        public Schema Response { get; set; }
+
+        /// <summary>
+        /// Union schema object for the 'error' attribute
+        /// </summary>
+        public UnionSchema Error { get; set; }
+
+        /// <summary>
+        /// Optional one-way attribute
+        /// </summary>
+        public bool? Oneway { get; set; }
+
+        /// <summary>
+        /// Constructor for Message class
+        /// </summary>
+        /// <param name="name">name property</param>
+        /// <param name="doc">doc property</param>
+        /// <param name="request">list of parameters</param>
+        /// <param name="response">response property</param>
+        /// <param name="error">error union schema</param>
+        public Message(string name, string doc, RecordSchema request, Schema response, UnionSchema error, bool? oneway)
+        {
+            if (string.IsNullOrEmpty(name)) throw new ArgumentNullException("name", "name cannot be null.");
+            this.Request = request;
+            this.Response = response;
+            this.Error = error;
+            this.Name = name;
+            this.Doc = doc;
+            this.Oneway = oneway;
+        }
+
+        /// <summary>
+        /// Parses the messages section of a protocol definition
+        /// </summary>
+        /// <param name="jmessage">messages JSON object</param>
+        /// <param name="names">list of parsed names</param>
+        /// <param name="encspace">enclosing namespace</param>
+        /// <returns></returns>
+        internal static Message Parse(JProperty jmessage, SchemaNames names, string encspace)
+        {
+            string name = jmessage.Name;
+            string doc = JsonHelper.GetOptionalString(jmessage.Value, "doc");
+            bool? oneway = JsonHelper.GetOptionalBoolean(jmessage.Value, "one-way");
+
+            PropertyMap props = Schema.GetProperties(jmessage.Value);
+            RecordSchema schema = RecordSchema.NewInstance(Schema.Type.Record, jmessage.Value as JObject, props, names, encspace);
+
+            JToken jresponse = jmessage.Value["response"];
+            var response = Schema.ParseJson(jresponse, names, encspace);
+
+            JToken jerrors = jmessage.Value["errors"];
+            UnionSchema uerrorSchema = null;
+            if (null != jerrors)
+            {
+                Schema errorSchema = Schema.ParseJson(jerrors, names, encspace);
+                if (!(errorSchema is UnionSchema))
+                    throw new AvroException("");
+
+                uerrorSchema = errorSchema as UnionSchema;
+            }
+
+            return new Message(name, doc, schema, response, uerrorSchema, oneway);
+        }
+
+        /// <summary>
+        /// Writes the messages section of a protocol definition
+        /// </summary>
+        /// <param name="writer">writer</param>
+        /// <param name="names">list of names written</param>
+        /// <param name="encspace">enclosing namespace</param>
+        internal void writeJson(Newtonsoft.Json.JsonTextWriter writer, SchemaNames names, string encspace)
+        {
+            writer.WriteStartObject();
+            JsonHelper.writeIfNotNullOrEmpty(writer, "doc", this.Doc);
+
+            if (null != this.Request)
+                this.Request.WriteJsonFields(writer, names, null);
+
+            if (null != this.Response)
+            {
+                writer.WritePropertyName("response");
+                writer.WriteValue(Response.Name);
+            }
+
+            if (null != this.Error)
+            {
+                writer.WritePropertyName("errors");
+                this.Error.WriteJson(writer, names, encspace);
+            }
+
+            if (null != Oneway)
+            {
+                writer.WritePropertyName("one-way");
+                writer.WriteValue(Oneway);
+            }
+
+            writer.WriteEndObject();
+        }
+    }
+}

Added: avro/trunk/lang/csharp/src/apache/main/Protocol/Protocol.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Protocol/Protocol.cs?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Protocol/Protocol.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Protocol/Protocol.cs Thu Mar 31 21:16:28 2011
@@ -0,0 +1,191 @@
+/**
+ * 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 Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+
+namespace Avro
+{
+    public class Protocol
+    {
+        /// <summary>
+        /// Name of the protocol
+        /// </summary>
+        public string Name { get; set; }
+
+        /// <summary>
+        /// Namespace of the protocol
+        /// </summary>
+        public string Namespace { get; set; }
+
+        /// <summary>
+        /// Documentation for the protocol
+        /// </summary>
+        public string Doc { get; set; }
+
+        /// <summary>
+        /// List of schemas objects representing the different schemas defined under the 'types' attribute
+        /// </summary>
+        public IList<Schema> Types { get; set; }
+
+        /// <summary>
+        /// List of message objects representing the different schemas defined under the 'messages' attribute
+        /// </summary>
+        public IDictionary<string,Message> Messages { get; set; }
+
+        /// <summary>
+        /// Constructor for Protocol class
+        /// </summary>
+        /// <param name="name">required name of protocol</param>
+        /// <param name="space">optional namespace</param>
+        /// <param name="doc">optional documentation</param>
+        /// <param name="types">required list of types</param>
+        /// <param name="messages">required list of messages</param>
+        public Protocol(string name, string space,
+                        string doc, IEnumerable<Schema> types,
+                        IDictionary<string,Message> messages)
+        {
+            if (string.IsNullOrEmpty(name)) throw new ArgumentNullException("name", "name cannot be null.");
+            if (null == types) throw new ArgumentNullException("types", "types cannot be null.");
+            if (null == messages) throw new ArgumentNullException("messages", "messages cannot be null.");
+
+            this.Name = name;
+            this.Namespace = space;
+            this.Doc = doc;
+            this.Types = new List<Schema>(types);
+            this.Messages = new Dictionary<string, Message>(messages);
+        }
+
+        /// <summary>
+        /// Parses the given JSON string to create a Protocol object
+        /// </summary>
+        /// <param name="jstring">JSON string</param>
+        /// <returns>Protocol object</returns>
+        public static Protocol Parse(string jstring)
+        {
+            if (string.IsNullOrEmpty(jstring)) throw new ArgumentNullException("json", "json cannot be null.");
+
+            JToken jtok = null;
+            try
+            {
+                jtok = JObject.Parse(jstring);
+            }
+            catch (Exception ex)
+            {
+                throw new ProtocolParseException("Invalid JSON format: " + jstring, ex);
+            }
+            return Parse(jtok);
+        }
+
+        /// <summary>
+        /// Parses the given JSON object to create a Protocol object
+        /// </summary>
+        /// <param name="jtok">JSON object</param>
+        /// <returns>Protocol object</returns>
+        private static Protocol Parse(JToken jtok)
+        {
+            string name = JsonHelper.GetRequiredString(jtok, "protocol");
+            string space = JsonHelper.GetOptionalString(jtok, "namespace");
+            string doc = JsonHelper.GetOptionalString(jtok, "doc");
+
+            var names = new SchemaNames();
+
+            JToken jtypes = jtok["types"];
+            var types = new List<Schema>();
+            if (jtypes is JArray)
+            {
+                foreach (JToken jtype in jtypes)
+                {
+                    var schema = Schema.ParseJson(jtype, names, space);
+                    types.Add(schema);
+                }
+            }
+
+            var messages = new Dictionary<string,Message>();
+            JToken jmessages = jtok["messages"];
+            if (null != jmessages)
+            {
+                foreach (JProperty jmessage in jmessages)
+                {
+                    var message = Message.Parse(jmessage, names, space);
+                    messages.Add(message.Name, message);
+                }
+            }
+
+            return new Protocol(name, space, doc, types, messages);
+        }
+
+        /// <summary>
+        /// Writes Protocol in JSON format
+        /// </summary>
+        /// <returns>JSON string</returns>
+        public override string ToString()
+        {
+            using (System.IO.StringWriter sw = new System.IO.StringWriter())
+            {
+                using (Newtonsoft.Json.JsonTextWriter writer = new Newtonsoft.Json.JsonTextWriter(sw))
+                {
+                    #if(DEBUG)
+                    writer.Formatting = Newtonsoft.Json.Formatting.Indented;
+                    #endif
+
+                    WriteJson(writer, new SchemaNames());
+                    writer.Flush();
+                    return sw.ToString();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Writes Protocol in JSON format
+        /// </summary>
+        /// <param name="writer">JSON writer</param>
+        /// <param name="names">list of named schemas already written</param>
+        internal void WriteJson(Newtonsoft.Json.JsonTextWriter writer, SchemaNames names)
+        {
+            writer.WriteStartObject();
+
+            JsonHelper.writeIfNotNullOrEmpty(writer, "protocol", this.Name);
+            JsonHelper.writeIfNotNullOrEmpty(writer, "namespace", this.Namespace);
+            JsonHelper.writeIfNotNullOrEmpty(writer, "doc", this.Doc);
+
+            writer.WritePropertyName("types");
+            writer.WriteStartArray();
+
+            foreach (Schema type in this.Types)
+                type.WriteJson(writer, names, this.Namespace);
+
+            writer.WriteEndArray();
+
+            writer.WritePropertyName("messages");
+            writer.WriteStartObject();
+
+            foreach (KeyValuePair<string,Message> message in this.Messages)
+            {
+                writer.WritePropertyName(message.Key);
+                message.Value.writeJson(writer, names, this.Namespace);
+            }
+
+            writer.WriteEndObject();
+            writer.WriteEndObject();
+        }
+    }
+}

Added: avro/trunk/lang/csharp/src/apache/main/Protocol/ProtocolParseException.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Protocol/ProtocolParseException.cs?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Protocol/ProtocolParseException.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Protocol/ProtocolParseException.cs Thu Mar 31 21:16:28 2011
@@ -0,0 +1,36 @@
+/**
+ * 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.Text;
+
+namespace Avro
+{
+    public class ProtocolParseException:AvroException
+    {
+        public ProtocolParseException(string s)
+            : base(s)
+        {
+        }
+
+        public ProtocolParseException(string s, Exception inner)
+            : base(s, inner)
+        {
+        }
+    }
+}

Added: avro/trunk/lang/csharp/src/apache/main/Schema/ArraySchema.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Schema/ArraySchema.cs?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Schema/ArraySchema.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Schema/ArraySchema.cs Thu Mar 31 21:16:28 2011
@@ -0,0 +1,111 @@
+/**
+ * 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 Newtonsoft.Json.Linq;
+
+namespace Avro
+{
+    /// <summary>
+    /// Class for array type schemas
+    /// </summary>
+    public class ArraySchema : UnnamedSchema
+    {
+        /// <summary>
+        /// Schema for the array 'type' attribute
+        /// </summary>
+        public Schema ItemSchema { get; set;  }
+
+        /// <summary>
+        /// Static class to return a new instance of ArraySchema
+        /// </summary>
+        /// <param name="jtok">JSON object for the array schema</param>
+        /// <param name="names">list of named schemas already parsed</param>
+        /// <param name="encspace">enclosing namespace for the array schema</param>
+        /// <returns></returns>
+        internal static ArraySchema NewInstance(JToken jtok, PropertyMap props, SchemaNames names, string encspace)
+        {
+            JToken jitem = jtok["items"];
+            if (null == jitem) throw new AvroTypeException("Array does not have 'items'");
+
+            return new ArraySchema(Schema.ParseJson(jitem, names, encspace), props);
+        }
+
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="items">schema for the array items type</param>
+        private ArraySchema(Schema items, PropertyMap props) : base(Type.Array, props)
+        {
+            if (null == items) throw new ArgumentNullException("items");
+            this.ItemSchema = items;
+        }
+
+        /// <summary>
+        /// Writes the array schema in JSON format
+        /// </summary>
+        /// <param name="writer">JSON writer</param>
+        /// <param name="names">list of named schemas already written</param>
+        /// <param name="encspace">enclosing namespace</param>
+        protected internal override void WriteJsonFields(Newtonsoft.Json.JsonTextWriter writer, SchemaNames names, string encspace)
+        {
+            writer.WritePropertyName("items");
+            ItemSchema.WriteJson(writer, names, encspace);
+        }
+
+        /// <summary>
+        /// Checks if this schema can read data written by the given schema. Used for decoding data.
+        /// </summary>
+        /// <param name="writerSchema">writer schema</param>
+        /// <returns>true if this and writer schema are compatible based on the AVRO specification, false otherwise</returns>
+        public override bool CanRead(Schema writerSchema)
+        {
+            if (writerSchema.Tag != Tag) return false;
+
+            ArraySchema that = writerSchema as ArraySchema;
+            return ItemSchema.CanRead(that.ItemSchema);
+        }
+
+        /// <summary>
+        /// Function to compare equality of two array schemas
+        /// </summary>
+        /// <param name="obj">other array schema</param>
+        /// <returns>true two schemas are equal, false otherwise</returns>
+        public override bool Equals(object obj)
+        {
+            if (this == obj) return true;
+
+            if (obj != null && obj is ArraySchema)
+            {
+                ArraySchema that = obj as ArraySchema;
+                if (ItemSchema.Equals(that.ItemSchema))
+                    return areEqual(that.Props, this.Props);
+            }
+            return false;
+        }
+
+        /// <summary>
+        /// Hashcode function
+        /// </summary>
+        /// <returns></returns>
+        public override int GetHashCode()
+        {
+            return 29 * ItemSchema.GetHashCode() + getHashCode(Props);
+        }
+    }
+}

Added: avro/trunk/lang/csharp/src/apache/main/Schema/AvroException.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Schema/AvroException.cs?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Schema/AvroException.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Schema/AvroException.cs Thu Mar 31 21:16:28 2011
@@ -0,0 +1,36 @@
+/**
+ * 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.Text;
+
+namespace Avro
+{
+    public class AvroException : Exception
+    {
+        public AvroException(string s)
+            : base(s)
+        {
+        }
+
+        public AvroException(string s, Exception inner)
+            : base(s, inner)
+        {
+        }
+    }
+}

Added: avro/trunk/lang/csharp/src/apache/main/Schema/AvroTypeException.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Schema/AvroTypeException.cs?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Schema/AvroTypeException.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Schema/AvroTypeException.cs Thu Mar 31 21:16:28 2011
@@ -0,0 +1,31 @@
+/**
+ * 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.Text;
+
+namespace Avro
+{
+    public class AvroTypeException : AvroException
+    {
+        public AvroTypeException(string s)
+            : base(s)
+        {
+        }
+    }
+}

Added: avro/trunk/lang/csharp/src/apache/main/Schema/EnumSchema.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Schema/EnumSchema.cs?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Schema/EnumSchema.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Schema/EnumSchema.cs Thu Mar 31 21:16:28 2011
@@ -0,0 +1,206 @@
+/**
+ * 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.Text;
+using Newtonsoft.Json.Linq;
+
+namespace Avro
+{
+    /// <summary>
+    /// Class for enum type schemas
+    /// </summary>
+    public class EnumSchema : NamedSchema
+    {
+        /// <summary>
+        /// List of strings representing the enum symbols
+        /// </summary>
+        public IList<string> Symbols { get; private set;  }
+
+        /// <summary>
+        /// Map of enum symbols and it's corresponding ordinal number
+        /// </summary>
+        private readonly IDictionary<string, int> symbolMap;
+
+        /// <summary>
+        /// Count of enum symbols
+        /// </summary>
+        public int Count { get { return Symbols.Count; } }
+
+        /// <summary>
+        /// Static function to return new instance of EnumSchema
+        /// </summary>
+        /// <param name="jtok">JSON object for enum schema</param>
+        /// <param name="names">list of named schema already parsed in</param>
+        /// <param name="encspace">enclosing namespace for the enum schema</param>
+        /// <returns>new instance of enum schema</returns>
+        internal static EnumSchema NewInstance(JToken jtok, PropertyMap props, SchemaNames names, string encspace)
+        {
+            SchemaName name = NamedSchema.GetName(jtok, encspace);
+            var aliases = NamedSchema.GetAliases(jtok, name.Space, name.EncSpace);
+
+            JArray jsymbols = jtok["symbols"] as JArray;
+            if (null == jsymbols)
+                throw new SchemaParseException("Enum has no symbols: " + name);
+
+            List<string> symbols = new List<string>();
+            IDictionary<string, int> symbolMap = new Dictionary<string, int>();
+            int i = 0;
+            foreach (JValue jsymbol in jsymbols)
+            {
+                string s = (string)jsymbol.Value;
+                if (symbolMap.ContainsKey(s))
+                    throw new SchemaParseException("Duplicate symbol: " + s);
+
+                symbolMap[s] = i++;
+                symbols.Add(s);
+            }
+            return new EnumSchema(name, aliases, symbols, symbolMap, props, names);
+        }
+
+        /// <summary>
+        /// Constructor for enum schema
+        /// </summary>
+        /// <param name="name">name of enum</param>
+        /// <param name="aliases">list of aliases for the name</param>
+        /// <param name="symbols">list of enum symbols</param>
+        /// <param name="symbolMap">map of enum symbols and value</param>
+        /// <param name="names">list of named schema already read</param>
+        private EnumSchema(SchemaName name, IList<SchemaName> aliases, List<string> symbols,
+                            IDictionary<String, int> symbolMap, PropertyMap props, SchemaNames names)
+                            : base(Type.Enumeration, name, aliases, props, names)
+        {
+            if (null == name.Name) throw new SchemaParseException("name cannot be null for enum schema.");
+            this.Symbols = symbols;
+            this.symbolMap = symbolMap;
+        }
+
+        /// <summary>
+        /// Writes enum schema in JSON format
+        /// </summary>
+        /// <param name="writer">JSON writer</param>
+        /// <param name="names">list of named schema already written</param>
+        /// <param name="encspace">enclosing namespace of the enum schema</param>
+        protected internal override void WriteJsonFields(Newtonsoft.Json.JsonTextWriter writer, 
+                                                            SchemaNames names, string encspace)
+        {
+            base.WriteJsonFields(writer, names, encspace);
+            writer.WritePropertyName("symbols");
+            writer.WriteStartArray();
+            foreach (string s in this.Symbols)
+                writer.WriteValue(s);
+            writer.WriteEndArray();
+        }
+
+        /// <summary>
+        /// Returns the position of the given symbol within this enum. 
+        /// Throws AvroException if the symbol is not found in this enum.
+        /// </summary>
+        /// <param name="symbol">name of the symbol to find</param>
+        /// <returns>position of the given symbol in this enum schema</returns>
+        public int Ordinal(string symbol)
+        {
+            int result;
+            if (symbolMap.TryGetValue(symbol, out result)) return result;
+            throw new AvroException("No such symbol: " + symbol);
+        }
+
+        /// <summary>
+        /// Returns the enum symbol of the given index to the list
+        /// </summary>
+        /// <param name="index">symbol index</param>
+        /// <returns>symbol name</returns>
+        public string this[int index]
+        {
+            get
+            {
+                if (index < Symbols.Count) return Symbols[index];
+                throw new AvroException("Enumeration out of range. Must be less than " + Symbols.Count + ", but is " + index);
+            }
+        }
+
+        /// <summary>
+        /// Checks if given symbol is in the list of enum symbols
+        /// </summary>
+        /// <param name="symbol">symbol to check</param>
+        /// <returns>true if symbol exist, false otherwise</returns>
+        public bool Contains(string symbol)
+        {
+            return symbolMap.ContainsKey(symbol);
+        }
+
+        /// <summary>
+        /// Returns an enumerator that enumerates the symbols in this enum schema in the order of their definition.
+        /// </summary>
+        /// <returns>Enumeration over the symbols of this enum schema</returns>
+        public IEnumerator<string> GetEnumerator()
+        {
+            return Symbols.GetEnumerator();
+        }
+
+        /// <summary>
+        /// Checks equality of two enum schema
+        /// </summary>
+        /// <param name="obj"></param>
+        /// <returns></returns>
+        public override bool Equals(object obj)
+        {
+            if (obj == this) return true;
+            if (obj != null && obj is EnumSchema)
+            {
+                EnumSchema that = obj as EnumSchema;
+                if (SchemaName.Equals(that.SchemaName) && Count == that.Count)
+                {
+                    for (int i = 0; i < Count; i++) if (!Symbols[i].Equals(that.Symbols[i])) return false;
+                    return areEqual(that.Props, this.Props);
+                }
+            }
+            return false;
+        }
+
+        /// <summary>
+        /// Hashcode function
+        /// </summary>
+        /// <returns></returns>
+        public override int GetHashCode()
+        {
+            int result = SchemaName.GetHashCode() + getHashCode(Props);
+            foreach (string s in Symbols) result += 23 * s.GetHashCode();
+            return result;
+        }
+
+        /// <summary>
+        /// Checks if this schema can read data written by the given schema. Used for decoding data.
+        /// </summary>
+        /// <param name="writerSchema">writer schema</param>
+        /// <returns>true if this and writer schema are compatible based on the AVRO specification, false otherwise</returns>
+        public override bool CanRead(Schema writerSchema)
+        {
+            if (writerSchema.Tag != Tag) return false;
+
+            EnumSchema that = writerSchema as EnumSchema;
+            if (!that.SchemaName.Equals(SchemaName))
+                if (!InAliases(that.SchemaName)) return false;
+
+            // we defer checking of symbols. Writer may have a symbol missing from the reader, 
+            // but if writer never used the missing symbol, then reader should still be able to read the data
+
+            return true;
+        }
+    }
+}

Added: avro/trunk/lang/csharp/src/apache/main/Schema/Field.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Schema/Field.cs?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Schema/Field.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Schema/Field.cs Thu Mar 31 21:16:28 2011
@@ -0,0 +1,245 @@
+/**
+ * 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.Text;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json;
+
+namespace Avro
+{
+
+    /// <summary>
+    /// Class for fields defined in a record
+    /// </summary>
+    public class Field
+    {
+        /// <summary>
+        /// Enum for the sorting order of record fields
+        /// </summary>
+        public enum SortOrder
+        {
+            ascending,
+            descending,
+            ignore
+        }
+
+        /// <summary>
+        /// Name of the field.
+        /// </summary>
+        public readonly string Name;
+
+        /// <summary>
+        /// List of aliases for the field name
+        /// </summary>
+        public readonly IList<string> aliases;
+
+        /// <summary>
+        /// Position of the field within its record.
+        /// </summary>
+        public int Pos { get; private set; }
+
+        /// <summary>
+        /// Documentation for the field, if any. Null if there is no documentation.
+        /// </summary>
+        public string Documentation { get; private set; }
+
+        /// <summary>
+        /// The default value for the field stored as JSON object, if defined. Otherwise, null.
+        /// </summary>
+        public JToken DefaultValue { get; private set; }
+
+        /// <summary>
+        /// Order of the field
+        /// </summary>
+        public SortOrder? Ordering { get; private set; }
+
+        /// <summary>
+        /// Field type's schema
+        /// </summary>
+        public Schema Schema { get; private set; }
+
+        /// <summary>
+        /// Custom properties for the field. We don't store the fields custom properties in
+        /// the field type's schema because if the field type is only a reference to the schema 
+        /// instead of an actual schema definition, then the schema could already have it's own set 
+        /// of custom properties when it was previously defined.
+        /// </summary>
+        private readonly PropertyMap Props;
+
+        /// <summary>
+        /// Static comparer object for JSON objects such as the fields default value
+        /// </summary>
+        internal static JTokenEqualityComparer JtokenEqual = new JTokenEqualityComparer();
+
+        /// <summary>
+        /// A flag to indicate if reader schema has a field that is missing from writer schema and has a default value
+        /// This is set in CanRead() which is always be called before deserializing data
+        /// </summary>
+
+        /// <summary>
+        /// Constructor for the field class
+        /// </summary>
+        /// <param name="schema">schema for the field type</param>
+        /// <param name="name">name of the field</param>
+        /// <param name="aliases">list of aliases for the name of the field</param>
+        /// <param name="pos">position of the field</param>
+        /// <param name="doc">documentation for the field</param>
+        /// <param name="defaultValue">field's default value if it exists</param>
+        /// <param name="sortorder">sort order of the field</param>
+        internal Field(Schema schema, string name, IList<string> aliases, int pos, string doc,
+                        JToken defaultValue, SortOrder sortorder, PropertyMap props)
+        {
+            if (string.IsNullOrEmpty(name)) throw new ArgumentNullException("name", "name cannot be null.");
+            if (null == schema) throw new ArgumentNullException("type", "type cannot be null.");
+            this.Schema = schema;
+            this.Name = name;
+            this.aliases = aliases;
+            this.Pos = pos;
+            this.Documentation = doc;
+            this.DefaultValue = defaultValue;
+            this.Ordering = sortorder;
+            this.Props = props;
+        }
+
+        /// <summary>
+        /// Writes the Field class in JSON format
+        /// </summary>
+        /// <param name="writer">JSON writer</param>
+        /// <param name="names">list of named schemas already written</param>
+        /// <param name="encspace">enclosing namespace for the field</param>
+        protected internal void writeJson(JsonTextWriter writer, SchemaNames names, string encspace)
+        {
+            writer.WriteStartObject();
+            JsonHelper.writeIfNotNullOrEmpty(writer, "name", this.Name);
+            JsonHelper.writeIfNotNullOrEmpty(writer, "doc", this.Documentation);
+
+            if (null != this.DefaultValue)
+            {
+                writer.WritePropertyName("default");
+                this.DefaultValue.WriteTo(writer, null);
+            }
+            if (null != this.Schema)
+            {
+                writer.WritePropertyName("type");
+                Schema.WriteJson(writer, names, encspace);
+            }
+
+            if (null != this.Props)
+                this.Props.WriteJson(writer);
+
+            if (null != aliases)
+            {
+                writer.WritePropertyName("aliases");
+                writer.WriteStartArray();
+                foreach (string name in aliases)
+                    writer.WriteValue(name);
+                writer.WriteEndArray();
+            }
+
+            writer.WriteEndObject();
+        }
+
+        /// <summary>
+        /// Parses the 'aliases' property from the given JSON token
+        /// </summary>
+        /// <param name="jtok">JSON object to read</param>
+        /// <returns>List of string that represents the list of alias. If no 'aliases' specified, then it returns null.</returns>
+        internal static IList<string> GetAliases(JToken jtok)
+        {
+            JToken jaliases = jtok["aliases"];
+            if (null == jaliases)
+                return null;
+
+            if (jaliases.Type != JTokenType.Array)
+                throw new SchemaParseException("Aliases must be of format JSON array of strings");
+
+            var aliases = new List<string>();
+            foreach (JToken jalias in jaliases)
+            {
+                if (jalias.Type != JTokenType.String)
+                    throw new SchemaParseException("Aliases must be of format JSON array of strings");
+
+                aliases.Add((string)jalias);
+            }
+            return aliases;
+        }
+
+        /// <summary>
+        /// Returns the field's custom property value given the property name
+        /// </summary>
+        /// <param name="key">custom property name</param>
+        /// <returns>custom property value</returns>
+        public string GetProperty(string key)
+        {
+            if (null == this.Props) return null;
+            string v;
+            return (this.Props.TryGetValue(key, out v)) ? v : null;
+        }
+
+        /// <summary>
+        /// Compares two field objects
+        /// </summary>
+        /// <param name="obj">field to compare with this field</param>
+        /// <returns>true if two fields are equal, false otherwise</returns>
+        public override bool Equals(object obj)
+        {
+            if (obj == this) return true;
+            if (obj != null && obj is Field)
+            {
+                Field that = obj as Field;
+                return areEqual(that.Name, Name) && that.Pos == Pos && areEqual(that.Documentation, Documentation)
+                    && areEqual(that.Ordering, Ordering) && JtokenEqual.Equals(that.DefaultValue, DefaultValue)
+                    && that.Schema.Equals(Schema) && areEqual(that.Props, this.Props);
+            }
+            return false;
+        }
+
+        /// <summary>
+        /// Compares two objects
+        /// </summary>
+        /// <param name="o1">first object</param>
+        /// <param name="o2">second object</param>
+        /// <returns>true if two objects are equal, false otherwise</returns>
+        private static bool areEqual(object o1, object o2)
+        {
+            return o1 == null ? o2 == null : o1.Equals(o2);
+        }
+
+        /// <summary>
+        /// Hash code function
+        /// </summary>
+        /// <returns></returns>
+        public override int GetHashCode()
+        {
+            return 17 * Name.GetHashCode() + Pos + 19 * getHashCode(Documentation) +
+                   23 * getHashCode(Ordering) + 29 * getHashCode(DefaultValue) + 31 * Schema.GetHashCode() +
+                   37 * getHashCode(Props);
+        }
+
+        /// <summary>
+        /// Hash code helper function
+        /// </summary>
+        /// <param name="obj"></param>
+        /// <returns></returns>
+        private static int getHashCode(object obj)
+        {
+            return obj == null ? 0 : obj.GetHashCode();
+        }
+    }
+}

Added: avro/trunk/lang/csharp/src/apache/main/Schema/FixedSchema.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Schema/FixedSchema.cs?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Schema/FixedSchema.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Schema/FixedSchema.cs Thu Mar 31 21:16:28 2011
@@ -0,0 +1,120 @@
+/**
+ * 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.Text;
+using Newtonsoft.Json.Linq;
+
+namespace Avro
+{
+    /// <summary>
+    /// Class for fixed schemas
+    /// </summary>
+    public class FixedSchema : NamedSchema
+    {
+        /// <summary>
+        /// Fixed size for the bytes
+        /// </summary>
+        public int Size { get; set; }
+
+        /// <summary>
+        /// Static function to return new instance of the fixed schema class
+        /// </summary>
+        /// <param name="jtok">JSON object for the fixed schema</param>
+        /// <param name="names">list of named schema already parsed in</param>
+        /// <param name="encspace">enclosing namespace of the fixed schema</param>
+        /// <returns></returns>
+        internal static FixedSchema NewInstance(JToken jtok, PropertyMap props, SchemaNames names, string encspace)
+        {
+            SchemaName name = NamedSchema.GetName(jtok, encspace);
+            var aliases = NamedSchema.GetAliases(jtok, name.Space, name.EncSpace);
+
+            return new FixedSchema(name, aliases, JsonHelper.GetRequiredInteger(jtok, "size"), props, names);
+        }
+
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="name">name of the fixed schema</param>
+        /// <param name="aliases">list of aliases for the name</param>
+        /// <param name="size">fixed size</param>
+        /// <param name="names">list of named schema already parsed in</param>
+        private FixedSchema(SchemaName name, IList<SchemaName> aliases, int size, PropertyMap props, SchemaNames names)
+                            : base(Type.Fixed, name, aliases, props, names)
+        {
+            if (null == name.Name) throw new SchemaParseException("name cannot be null for fixed schema.");
+            if (size <= 0) throw new ArgumentOutOfRangeException("size", "size must be greater than zero.");
+            this.Size = size;
+        }
+
+        /// <summary>
+        /// Writes the fixed schema class in JSON format
+        /// </summary>
+        /// <param name="writer">JSON writer</param>
+        /// <param name="names">list of named schema already written</param>
+        /// <param name="encspace">enclosing namespace for the fixed schema</param>
+        protected internal override void WriteJsonFields(Newtonsoft.Json.JsonTextWriter writer, SchemaNames names, string encspace)
+        {
+            base.WriteJsonFields(writer, names, encspace);
+            writer.WritePropertyName("size");
+            writer.WriteValue(this.Size);
+        }
+
+        /// <summary>
+        /// Compares two fixed schemas
+        /// </summary>
+        /// <param name="obj">fixed schema to compare against this schema</param>
+        /// <returns>true if two schemas are the same, false otherwise</returns>
+        public override bool Equals(object obj)
+        {
+            if (obj == this) return true;
+
+            if (obj != null && obj is FixedSchema)
+            {
+                FixedSchema that = obj as FixedSchema;
+                return SchemaName.Equals(that.SchemaName) && Size == that.Size && areEqual(that.Props, this.Props);
+            }
+            return false;
+        }
+
+        /// <summary>
+        /// Hash code function
+        /// </summary>
+        /// <returns></returns>
+        public override int GetHashCode()
+        {
+            return 53 * SchemaName.GetHashCode() + 47 * Size + getHashCode(Props);
+        }
+
+        /// <summary>
+        /// Checks if this schema can read data written by the given schema. Used for decoding data.
+        /// </summary>
+        /// <param name="writerSchema">writer schema</param>
+        /// <returns>true if this and writer schema are compatible based on the AVRO specification, false otherwise</returns>
+        public override bool CanRead(Schema writerSchema)
+        {
+            if (writerSchema.Tag != Tag) return false;
+            FixedSchema that = writerSchema as FixedSchema;
+            if (that.Size != Size) return false;
+            if (that.SchemaName.Equals(SchemaName))
+                return true;
+            else
+                return InAliases(that.SchemaName);
+        }
+    }
+}

Added: avro/trunk/lang/csharp/src/apache/main/Schema/JsonHelper.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Schema/JsonHelper.cs?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Schema/JsonHelper.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Schema/JsonHelper.cs Thu Mar 31 21:16:28 2011
@@ -0,0 +1,122 @@
+/**
+ * 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.Text;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json;
+
+namespace Avro
+{
+    class JsonHelper
+    {
+        /// <summary>
+        /// Retrieves the optional string property value for the given property name from the given JSON object.
+        /// This throws an exception if property exists but it is not a string.
+        /// </summary>
+        /// <param name="jtok">JSON object to read</param>
+        /// <param name="field">property name</param>
+        /// <returns>property value if property exists, null if property doesn't exist in the JSON object</returns>
+        public static string GetOptionalString(JToken jtok, string field)
+        {
+            if (null == jtok) throw new ArgumentNullException("jtok", "jtok cannot be null.");
+            if (string.IsNullOrEmpty(field)) throw new ArgumentNullException("field", "field cannot be null.");
+
+            JToken child = jtok[field];
+            if (null == child) return null;
+
+            if (child.Type == JTokenType.String)
+            {
+                string value = child.ToString();
+                return value.Trim('\"');
+            }
+            throw new SchemaParseException("Field " + field + " is not a string");
+        }
+
+        /// <summary>
+        /// Retrieves the required string property value for the given property name from the given JSON object.
+        /// </summary>
+        /// <param name="jtok">JSON object to read</param>
+        /// <param name="field">property name</param>
+        /// <returns>property value</returns>
+        public static string GetRequiredString(JToken jtok, string field)
+        {
+            string value = GetOptionalString(jtok, field);
+            if (string.IsNullOrEmpty(value)) throw new SchemaParseException(string.Format("No \"{0}\" JSON field: {1}", field, jtok));
+            return value;
+        }
+
+        /// <summary>
+        /// Retrieves the required int property value for the given property name from the given JSON object.
+        /// </summary>
+        /// <param name="jtok">JSON object to read</param>
+        /// <param name="field">property name</param>
+        /// <returns>property value</returns>
+        public static int GetRequiredInteger(JToken jtok, string field)
+        {
+            ensureValidFieldName(field);
+            JToken child = jtok[field];
+            if (null == child) throw new SchemaParseException(string.Format("No \"{0}\" JSON field: {1}", field, jtok));
+
+            if (child.Type == JTokenType.Integer) return (int) child;
+            throw new SchemaParseException("Field " + field + " is not an integer");
+        }
+
+        /// <summary>
+        /// Retrieves the optional boolean property value for the given property name from the given JSON object.
+        /// </summary>
+        /// <param name="jtok">JSON object to read</param>
+        /// <param name="field">property name</param>
+        /// <returns>null if property doesn't exist, otherise returns property boolean value</returns>
+        public static bool? GetOptionalBoolean(JToken jtok, string field)
+        {
+            if (null == jtok) throw new ArgumentNullException("jtok", "jtok cannot be null.");
+            if (string.IsNullOrEmpty(field)) throw new ArgumentNullException("field", "field cannot be null.");
+
+            JToken child = jtok[field];
+            if (null == child) return null;
+
+            if (child.Type == JTokenType.Boolean)
+                return (bool)child;
+
+            throw new SchemaParseException("Field " + field + " is not a boolean");
+        }
+
+        /// <summary>
+        /// Writes JSON property name and value if value is not null
+        /// </summary>
+        /// <param name="writer">JSON writer</param>
+        /// <param name="key">property name</param>
+        /// <param name="value">property value</param>
+        internal static void writeIfNotNullOrEmpty(JsonTextWriter writer, string key, string value)
+        {
+            if (string.IsNullOrEmpty(value)) return;
+            writer.WritePropertyName(key);
+            writer.WriteValue(value);
+        }
+
+        /// <summary>
+        /// Checks if given name is not null or empty
+        /// </summary>
+        /// <param name="name"></param>
+        private static void ensureValidFieldName(string name)
+        {
+            if (string.IsNullOrEmpty(name)) throw new ArgumentNullException("name");
+        }
+    }
+}

Added: avro/trunk/lang/csharp/src/apache/main/Schema/MapSchema.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Schema/MapSchema.cs?rev=1087439&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Schema/MapSchema.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Schema/MapSchema.cs Thu Mar 31 21:16:28 2011
@@ -0,0 +1,112 @@
+/**
+ * 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.Text;
+using Newtonsoft.Json.Linq;
+
+namespace Avro
+{
+    /// <summary>
+    /// Class for map schemas
+    /// </summary>
+    public class MapSchema : UnnamedSchema
+    {
+        /// <summary>
+        /// Schema for map values type
+        /// </summary>
+        public Schema ValueSchema { get; set; }
+
+        /// <summary>
+        /// Static function to return new instance of map schema
+        /// </summary>
+        /// <param name="jtok">JSON object for the map schema</param>
+        /// <param name="names">list of named schemas already read</param>
+        /// <param name="encspace">enclosing namespace of the map schema</param>
+        /// <returns></returns>
+        internal static MapSchema NewInstance(JToken jtok, PropertyMap props, SchemaNames names, string encspace)
+        {
+            JToken jvalue = jtok["values"];
+            if (null == jvalue) throw new AvroTypeException("Map does not have 'values'");
+
+            return new MapSchema(Schema.ParseJson(jvalue, names, encspace), props);
+        }
+
+        /// <summary>
+        /// Constructor for map schema class
+        /// </summary>
+        /// <param name="valueSchema">schema for map values type</param>
+        private MapSchema(Schema valueSchema, PropertyMap props) : base(Type.Map, props)
+        {
+            if (null == valueSchema) throw new ArgumentNullException("valueSchema", "valueSchema cannot be null.");
+            this.ValueSchema = valueSchema;
+        }
+
+        /// <summary>
+        /// Writes map schema in JSON format
+        /// </summary>
+        /// <param name="writer">JSON writer</param>
+        /// <param name="names">list of named schemas already written</param>
+        /// <param name="encspace">enclosing namespace of the map schema</param>
+        protected internal override void WriteJsonFields(Newtonsoft.Json.JsonTextWriter writer, SchemaNames names, string encspace)
+        {
+            writer.WritePropertyName("values");
+            ValueSchema.WriteJson(writer, names, encspace);
+        }
+
+        /// <summary>
+        /// Checks if this schema can read data written by the given schema. Used for decoding data.
+        /// </summary>
+        /// <param name="writerSchema">writer schema</param>
+        /// <returns>true if this and writer schema are compatible based on the AVRO specification, false otherwise</returns>
+        public override bool CanRead(Schema writerSchema)
+        {
+            if (writerSchema.Tag != Tag) return false;
+
+            MapSchema that = writerSchema as MapSchema;
+            return ValueSchema.CanRead(that.ValueSchema);
+        }
+
+        /// <summary>
+        /// Compares equality of two map schemas
+        /// </summary>
+        /// <param name="obj">map schema to compare against this schema</param>
+        /// <returns>true if two schemas are equal, false otherwise</returns>
+        public override bool Equals(object obj)
+        {
+            if (this == obj) return true;
+
+            if (obj != null && obj is MapSchema)
+            {
+                MapSchema that = obj as MapSchema;
+                if (ValueSchema.Equals(that.ValueSchema))
+                    return areEqual(that.Props, this.Props);
+            }
+            return false;
+        }
+
+        /// <summary>
+        /// Hashcode function
+        /// </summary>
+        /// <returns></returns>
+        public override int GetHashCode()
+        {
+            return 29 * ValueSchema.GetHashCode() + getHashCode(Props);
+        }
+    }
+}