using System; using System.Collections.Generic; using System.Linq; namespace LeanCloud.Storage.Internal { public class AVIncrementOperation : IAVFieldOperation { private static readonly IDictionary, Func> adders; static AVIncrementOperation() { // Defines adders for all of the implicit conversions: http://msdn.microsoft.com/en-US/library/y5b434w4(v=vs.80).aspx adders = new Dictionary, Func> { {new Tuple(typeof(sbyte), typeof(sbyte)), (left, right) => (sbyte)left + (sbyte)right}, {new Tuple(typeof(sbyte), typeof(short)), (left, right) => (sbyte)left + (short)right}, {new Tuple(typeof(sbyte), typeof(int)), (left, right) => (sbyte)left + (int)right}, {new Tuple(typeof(sbyte), typeof(long)), (left, right) => (sbyte)left + (long)right}, {new Tuple(typeof(sbyte), typeof(float)), (left, right) => (sbyte)left + (float)right}, {new Tuple(typeof(sbyte), typeof(double)), (left, right) => (sbyte)left + (double)right}, {new Tuple(typeof(sbyte), typeof(decimal)), (left, right) => (sbyte)left + (decimal)right}, {new Tuple(typeof(byte), typeof(byte)), (left, right) => (byte)left + (byte)right}, {new Tuple(typeof(byte), typeof(short)), (left, right) => (byte)left + (short)right}, {new Tuple(typeof(byte), typeof(ushort)), (left, right) => (byte)left + (ushort)right}, {new Tuple(typeof(byte), typeof(int)), (left, right) => (byte)left + (int)right}, {new Tuple(typeof(byte), typeof(uint)), (left, right) => (byte)left + (uint)right}, {new Tuple(typeof(byte), typeof(long)), (left, right) => (byte)left + (long)right}, {new Tuple(typeof(byte), typeof(ulong)), (left, right) => (byte)left + (ulong)right}, {new Tuple(typeof(byte), typeof(float)), (left, right) => (byte)left + (float)right}, {new Tuple(typeof(byte), typeof(double)), (left, right) => (byte)left + (double)right}, {new Tuple(typeof(byte), typeof(decimal)), (left, right) => (byte)left + (decimal)right}, {new Tuple(typeof(short), typeof(short)), (left, right) => (short)left + (short)right}, {new Tuple(typeof(short), typeof(int)), (left, right) => (short)left + (int)right}, {new Tuple(typeof(short), typeof(long)), (left, right) => (short)left + (long)right}, {new Tuple(typeof(short), typeof(float)), (left, right) => (short)left + (float)right}, {new Tuple(typeof(short), typeof(double)), (left, right) => (short)left + (double)right}, {new Tuple(typeof(short), typeof(decimal)), (left, right) => (short)left + (decimal)right}, {new Tuple(typeof(ushort), typeof(ushort)), (left, right) => (ushort)left + (ushort)right}, {new Tuple(typeof(ushort), typeof(int)), (left, right) => (ushort)left + (int)right}, {new Tuple(typeof(ushort), typeof(uint)), (left, right) => (ushort)left + (uint)right}, {new Tuple(typeof(ushort), typeof(long)), (left, right) => (ushort)left + (long)right}, {new Tuple(typeof(ushort), typeof(ulong)), (left, right) => (ushort)left + (ulong)right}, {new Tuple(typeof(ushort), typeof(float)), (left, right) => (ushort)left + (float)right}, {new Tuple(typeof(ushort), typeof(double)), (left, right) => (ushort)left + (double)right}, {new Tuple(typeof(ushort), typeof(decimal)), (left, right) => (ushort)left + (decimal)right}, {new Tuple(typeof(int), typeof(int)), (left, right) => (int)left + (int)right}, {new Tuple(typeof(int), typeof(long)), (left, right) => (int)left + (long)right}, {new Tuple(typeof(int), typeof(float)), (left, right) => (int)left + (float)right}, {new Tuple(typeof(int), typeof(double)), (left, right) => (int)left + (double)right}, {new Tuple(typeof(int), typeof(decimal)), (left, right) => (int)left + (decimal)right}, {new Tuple(typeof(uint), typeof(uint)), (left, right) => (uint)left + (uint)right}, {new Tuple(typeof(uint), typeof(long)), (left, right) => (uint)left + (long)right}, {new Tuple(typeof(uint), typeof(ulong)), (left, right) => (uint)left + (ulong)right}, {new Tuple(typeof(uint), typeof(float)), (left, right) => (uint)left + (float)right}, {new Tuple(typeof(uint), typeof(double)), (left, right) => (uint)left + (double)right}, {new Tuple(typeof(uint), typeof(decimal)), (left, right) => (uint)left + (decimal)right}, {new Tuple(typeof(long), typeof(long)), (left, right) => (long)left + (long)right}, {new Tuple(typeof(long), typeof(float)), (left, right) => (long)left + (float)right}, {new Tuple(typeof(long), typeof(double)), (left, right) => (long)left + (double)right}, {new Tuple(typeof(long), typeof(decimal)), (left, right) => (long)left + (decimal)right}, {new Tuple(typeof(char), typeof(char)), (left, right) => (char)left + (char)right}, {new Tuple(typeof(char), typeof(ushort)), (left, right) => (char)left + (ushort)right}, {new Tuple(typeof(char), typeof(int)), (left, right) => (char)left + (int)right}, {new Tuple(typeof(char), typeof(uint)), (left, right) => (char)left + (uint)right}, {new Tuple(typeof(char), typeof(long)), (left, right) => (char)left + (long)right}, {new Tuple(typeof(char), typeof(ulong)), (left, right) => (char)left + (ulong)right}, {new Tuple(typeof(char), typeof(float)), (left, right) => (char)left + (float)right}, {new Tuple(typeof(char), typeof(double)), (left, right) => (char)left + (double)right}, {new Tuple(typeof(char), typeof(decimal)), (left, right) => (char)left + (decimal)right}, {new Tuple(typeof(float), typeof(float)), (left, right) => (float)left + (float)right}, {new Tuple(typeof(float), typeof(double)), (left, right) => (float)left + (double)right}, {new Tuple(typeof(ulong), typeof(ulong)), (left, right) => (ulong)left + (ulong)right}, {new Tuple(typeof(ulong), typeof(float)), (left, right) => (ulong)left + (float)right}, {new Tuple(typeof(ulong), typeof(double)), (left, right) => (ulong)left + (double)right}, {new Tuple(typeof(ulong), typeof(decimal)), (left, right) => (ulong)left + (decimal)right}, {new Tuple(typeof(double), typeof(double)), (left, right) => (double)left + (double)right}, {new Tuple(typeof(decimal), typeof(decimal)), (left, right) => (decimal)left + (decimal)right} }; // Generate the adders in the other direction foreach (var pair in adders.Keys.ToList()) { if (pair.Item1.Equals(pair.Item2)) { continue; } var reversePair = new Tuple(pair.Item2, pair.Item1); var func = adders[pair]; adders[reversePair] = (left, right) => func(right, left); } } private object amount; public AVIncrementOperation(object amount) { this.amount = amount; } public object Encode() { return new Dictionary { {"__op", "Increment"}, {"amount", amount} }; } private static object Add(object obj1, object obj2) { Func adder; if (adders.TryGetValue(new Tuple(obj1.GetType(), obj2.GetType()), out adder)) { return adder(obj1, obj2); } throw new InvalidCastException("Cannot add " + obj1.GetType() + " to " + obj2.GetType()); } public IAVFieldOperation MergeWithPrevious(IAVFieldOperation previous) { if (previous == null) { return this; } if (previous is AVDeleteOperation) { return new AVSetOperation(amount); } if (previous is AVSetOperation) { var otherAmount = ((AVSetOperation)previous).Value; if (otherAmount is string) { throw new InvalidOperationException("Cannot increment a non-number type."); } var myAmount = amount; return new AVSetOperation(Add(otherAmount, myAmount)); } if (previous is AVIncrementOperation) { object otherAmount = ((AVIncrementOperation)previous).Amount; object myAmount = amount; return new AVIncrementOperation(Add(otherAmount, myAmount)); } throw new InvalidOperationException("Operation is invalid after previous operation."); } public object Apply(object oldValue, string key) { if (oldValue is string) { throw new InvalidOperationException("Cannot increment a non-number type."); } object otherAmount = oldValue ?? 0; object myAmount = amount; return Add(otherAmount, myAmount); } public object Amount { get { return amount; } } } }